<commit_before>// Package context provides a mechanism for transparently tracking contextual
// state associated to the current goroutine and even across goroutines.
package context

import (
	"sync"
)

// Manager provides the ability to create and access Contexts.
type Manager interface {
	// Enter enters a new level on the current Context stack, creating a new Context
	// if necessary.
	Enter() Context

	// Go starts the given function on a new goroutine but sharing the context of
	// the current goroutine (if it has one).
	Go(func())

	// PutGlobal puts the given key->value pair into the global context.
	PutGlobal(key string, value interface{})

	// PutGlobalDynamic puts a key->value pair into the global context where the
	// value is generated by a function that gets evaluated at every Read. If the
	// value is a map[string]interface{}, we will unpack the map and set each
	// contained key->value pair independently.
	PutGlobalDynamic(key string, valueFN func() interface{})

	// AsMap returns a map containing all values from the supplied obj if it is a
	// Contextual, plus any addition values from along the stack, plus globals if so
	// specified.
	AsMap(obj interface{}, includeGlobals bool) Map

	// Get gets the value at the given key from the current context, ascending through
	// the context hierarchy until it finds a value, or returning the global value if none
	// found in contexts.
	Get(key string) (interface{}, bool)
}

type manager struct {
	contexts   map[uint64]*context
	mxContexts sync.RWMutex
	global     Map
	mxGlobal   sync.RWMutex
}

// NewManager creates a new Manager
func NewManager() Manager {
	return &manager{
		contexts: make(map[uint64]*context),
		global:   make(Map),
	}
}

// Contextual is an interface for anything that maintains its own context.
type Contextual interface {
	// Fill fills the given Map with all of this Contextual's context
	Fill(m Map)
}

// Map is a map of key->value pairs.
type Map map[string]interface{}

// Fill implements the method from the Contextual interface.
func (_m Map) Fill(m Map) {
	for key, value := range _m {
		m[key] = value
	}
}

// Context is a context containing key->value pairs
type Context interface {
	// Enter enters a new level on this Context stack.
	Enter() Context

	// Go starts the given function on a new goroutine.
	Go(fn func())

	// Exit exits the current level on this Context stack.
	Exit()

	// Put puts a key->value pair into the current level of the context stack.
	Put(key string, value interface{}) Context

	// PutIfAbsent puts the given key->value pair into the current level of the
	// context stack if and only if that key is defined nowhere within the context
	// stack (including parent contexts).
	PutIfAbsent(key string, value interface{}) Context

	// PutDynamic puts a key->value pair into the current level of the context
	// stack where the value is generated by a function that gets evaluated at
	// every Read. If the value is a map[string]interface{}, we will unpack the
	// map and set each contained key->value pair independently.
	PutDynamic(key string, valueFN func() interface{}) Context

	// Fill fills the given map with data from this Context
	Fill(m Map)

	// AsMap returns a map containing all values from the supplied obj if it is a
	// Contextual, plus any addition values from along the stack, plus globals if
	// so specified.
	AsMap(obj interface{}, includeGlobals bool) Map

	// Get gets the value at the given key, ascending through the context hierarchy
	// until it finds a value, or returning the global value if none found in contexts.
	Get(key string) (interface{}, bool)
}

type context struct {
	cm           *manager
	id           uint64
	parent       *context
	branchedFrom *context
	data         Map
	mx           sync.RWMutex
}

type dynval struct {
	fn func() interface{}
}

func (cm *manager) Enter() Context {
	return cm.enter(curGoroutineID())
}

func (cm *manager) enter(id uint64) *context {
	cm.mxContexts.Lock()
	parentOrNil := cm.contexts[id]
	c := cm.makeContext(id, parentOrNil, nil)
	cm.contexts[id] = c
	cm.mxContexts.Unlock()
	return c
}

func (cm *manager) exit(id uint64, parent *context) {
	cm.mxContexts.Lock()
	if parent == nil {
		delete(cm.contexts, id)
	} else {
		cm.contexts[id] = parent
	}
	cm.mxContexts.Unlock()
}

func (cm *manager) branch(id uint64, from *context) {
	next := cm.makeContext(id, nil, from)
	cm.mxContexts.Lock()
	cm.contexts[id] = next
	cm.mxContexts.Unlock()
}

func (cm *manager) merge(id uint64) {
	cm.mxContexts.Lock()
	delete(cm.contexts, id)
	cm.mxContexts.Unlock()
}

func (c *context) Enter() Context {
	c.mx.RLock()
	id := c.id
	c.mx.RUnlock()
	return c.cm.enter(id)
}

func (c *context) Go(fn func()) {
	go func() {
		id := curGoroutineID()
		c.cm.branch(id, c)
		fn()
		c.cm.merge(id)
	}()
}

func (cm *manager) Go(fn func()) {
	c := cm.currentContext()
	if c != nil {
		c.Go(fn)
	} else {
		go fn()
	}
}

func (cm *manager) makeContext(id uint64, parent *context, branchedFrom *context) *context {
	return &context{
		cm:           cm,
		id:           id,
		parent:       parent,
		branchedFrom: branchedFrom,
		data:         make(Map),
	}
}

func (c *context) Exit() {
	c.mx.RLock()
	id := c.id
	parent := c.parent
	c.mx.RUnlock()
	c.cm.exit(id, parent)
}

func (c *context) Put(key string, value interface{}) Context {
	c.mx.Lock()
	c.data[key] = value
	c.mx.Unlock()
	return c
}

func (c *context) PutIfAbsent(key string, value interface{}) Context {
	for ctx := c; ctx != nil; {
		ctx.mx.RLock()
		_, exists := ctx.data[key]
		next := ctx.parent
		if next == nil {
			next = ctx.branchedFrom
		}
		ctx.mx.RUnlock()
		if exists {
			return c
		}
		ctx = next
	}

	// Value not set, set it
	return c.Put(key, value)
}

func (c *context) PutDynamic(key string, valueFN func() interface{}) Context {
	value := &dynval{valueFN}
	c.mx.Lock()
	c.data[key] = value
	c.mx.Unlock()
	return c
}

func (cm *manager) PutGlobal(key string, value interface{}) {
	cm.mxGlobal.Lock()
	cm.global[key] = value
	cm.mxGlobal.Unlock()
}

func (cm *manager) PutGlobalDynamic(key string, valueFN func() interface{}) {
	value := &dynval{valueFN}
	cm.mxGlobal.Lock()
	cm.global[key] = value
	cm.mxGlobal.Unlock()
}

func (c *context) Fill(m Map) {
	for ctx := c; ctx != nil; {
		ctx.mx.RLock()
		fill(m, ctx.data)
		next := ctx.parent
		if next == nil {
			next = ctx.branchedFrom
		}
		ctx.mx.RUnlock()
		ctx = next
	}
}

func (cm *manager) AsMap(obj interface{}, includeGlobals bool) Map {
	return cm.currentContext().asMap(cm, obj, includeGlobals)
}

func (c *context) AsMap(obj interface{}, includeGlobals bool) Map {
	return c.asMap(c.cm, obj, includeGlobals)
}

func (c *context) asMap(cm *manager, obj interface{}, includeGlobals bool) Map {
	result := make(Map, 0)
	cl, ok := obj.(Contextual)
	if ok {
		cl.Fill(result)
	}
	if c != nil {
		c.Fill(result)
	}
	if includeGlobals {
		cm.mxGlobal.RLock()
		fill(result, cm.global)
		cm.mxGlobal.RUnlock()
	}
	return result
}

func (cm *manager) Get(key string) (interface{}, bool) {
	c := cm.currentContext()
	if c != nil {
		return c.Get(key)
	}
	cm.mxGlobal.RLock()
	result, found := cm.global[key]
	cm.mxGlobal.RUnlock()
	return result, found
}

func (c *context) Get(key string) (interface{}, bool) {
	result, found := c.data[key]
	if found {
		return result, found
	}
	if c.parent != nil {
		return c.parent.Get(key)
	}
	c.cm.mxGlobal.Lock()
	result, found = c.cm.global[key]
	c.cm.mxGlobal.Unlock()
	return result, found
}

func fill(m Map, from Map) {
	if m != nil {
		doFill := func(key string, _value interface{}) {
			switch value := _value.(type) {
			case map[string]interface{}:
				for k, v := range value {
					m[k] = v
				}
			default:
				m[key] = value
			}
		}

		for key, value := range from {
			_, alreadyRead := m[key]
			if !alreadyRead {
				switch v := value.(type) {
				case *dynval:
					doFill(key, v.fn())
				default:
					doFill(key, v)
				}
			}
		}
	}
}

func (cm *manager) currentContext() *context {
	id := curGoroutineID()
	cm.mxContexts.RLock()
	c := cm.contexts[id]
	cm.mxContexts.RUnlock()
	return c
}
<commit_msg>Added Get()<commit_after>// Package context provides a mechanism for transparently tracking contextual
// state associated to the current goroutine and even across goroutines.
package context

import (
	"sync"
)

// Manager provides the ability to create and access Contexts.
type Manager interface {
	// Enter enters a new level on the current Context stack, creating a new Context
	// if necessary.
	Enter() Context

	// Go starts the given function on a new goroutine but sharing the context of
	// the current goroutine (if it has one).
	Go(func())

	// PutGlobal puts the given key->value pair into the global context.
	PutGlobal(key string, value interface{})

	// PutGlobalDynamic puts a key->value pair into the global context where the
	// value is generated by a function that gets evaluated at every Read. If the
	// value is a map[string]interface{}, we will unpack the map and set each
	// contained key->value pair independently.
	PutGlobalDynamic(key string, valueFN func() interface{})

	// AsMap returns a map containing all values from the supplied obj if it is a
	// Contextual, plus any addition values from along the stack, plus globals if so
	// specified.
	AsMap(obj interface{}, includeGlobals bool) Map

	// Get gets the value at the given key from the current context, ascending through
	// the context hierarchy until it finds a value, or returning the global value if none
	// found in contexts.
	Get(key string) (interface{}, bool)
}

type manager struct {
	contexts   map[uint64]*context
	mxContexts sync.RWMutex
	global     Map
	mxGlobal   sync.RWMutex
}

// NewManager creates a new Manager
func NewManager() Manager {
	return &manager{
		contexts: make(map[uint64]*context),
		global:   make(Map),
	}
}

// Contextual is an interface for anything that maintains its own context.
type Contextual interface {
	// Fill fills the given Map with all of this Contextual's context
	Fill(m Map)
}

// Map is a map of key->value pairs.
type Map map[string]interface{}

// Fill implements the method from the Contextual interface.
func (_m Map) Fill(m Map) {
	for key, value := range _m {
		m[key] = value
	}
}

// Context is a context containing key->value pairs
type Context interface {
	// Enter enters a new level on this Context stack.
	Enter() Context

	// Go starts the given function on a new goroutine.
	Go(fn func())

	// Exit exits the current level on this Context stack.
	Exit()

	// Put puts a key->value pair into the current level of the context stack.
	Put(key string, value interface{}) Context

	// PutIfAbsent puts the given key->value pair into the current level of the
	// context stack if and only if that key is defined nowhere within the context
	// stack (including parent contexts).
	PutIfAbsent(key string, value interface{}) Context

	// PutDynamic puts a key->value pair into the current level of the context
	// stack where the value is generated by a function that gets evaluated at
	// every Read. If the value is a map[string]interface{}, we will unpack the
	// map and set each contained key->value pair independently.
	PutDynamic(key string, valueFN func() interface{}) Context

	// Fill fills the given map with data from this Context
	Fill(m Map)

	// AsMap returns a map containing all values from the supplied obj if it is a
	// Contextual, plus any addition values from along the stack, plus globals if
	// so specified.
	AsMap(obj interface{}, includeGlobals bool) Map

	// Get gets the value at the given key, ascending through the context hierarchy
	// until it finds a value, or returning the global value if none found in contexts.
	Get(key string) (interface{}, bool)
}

type context struct {
	cm           *manager
	id           uint64
	parent       *context
	branchedFrom *context
	data         Map
	mx           sync.RWMutex
}

type dynval struct {
	fn func() interface{}
}

func (cm *manager) Enter() Context {
	return cm.enter(curGoroutineID())
}

func (cm *manager) enter(id uint64) *context {
	cm.mxContexts.Lock()
	parentOrNil := cm.contexts[id]
	c := cm.makeContext(id, parentOrNil, nil)
	cm.contexts[id] = c
	cm.mxContexts.Unlock()
	return c
}

func (cm *manager) exit(id uint64, parent *context) {
	cm.mxContexts.Lock()
	if parent == nil {
		delete(cm.contexts, id)
	} else {
		cm.contexts[id] = parent
	}
	cm.mxContexts.Unlock()
}

func (cm *manager) branch(id uint64, from *context) {
	next := cm.makeContext(id, nil, from)
	cm.mxContexts.Lock()
	cm.contexts[id] = next
	cm.mxContexts.Unlock()
}

func (cm *manager) merge(id uint64) {
	cm.mxContexts.Lock()
	delete(cm.contexts, id)
	cm.mxContexts.Unlock()
}

func (c *context) Enter() Context {
	c.mx.RLock()
	id := c.id
	c.mx.RUnlock()
	return c.cm.enter(id)
}

func (c *context) Go(fn func()) {
	go func() {
		id := curGoroutineID()
		c.cm.branch(id, c)
		fn()
		c.cm.merge(id)
	}()
}

func (cm *manager) Go(fn func()) {
	c := cm.currentContext()
	if c != nil {
		c.Go(fn)
	} else {
		go fn()
	}
}

func (cm *manager) makeContext(id uint64, parent *context, branchedFrom *context) *context {
	return &context{
		cm:           cm,
		id:           id,
		parent:       parent,
		branchedFrom: branchedFrom,
		data:         make(Map),
	}
}

func (c *context) Exit() {
	c.mx.RLock()
	id := c.id
	parent := c.parent
	c.mx.RUnlock()
	c.cm.exit(id, parent)
}

func (c *context) Put(key string, value interface{}) Context {
	c.mx.Lock()
	c.data[key] = value
	c.mx.Unlock()
	return c
}

func (c *context) PutIfAbsent(key string, value interface{}) Context {
	for ctx := c; ctx != nil; {
		ctx.mx.RLock()
		_, exists := ctx.data[key]
		next := ctx.parent
		if next == nil {
			next = ctx.branchedFrom
		}
		ctx.mx.RUnlock()
		if exists {
			return c
		}
		ctx = next
	}

	// Value not set, set it
	return c.Put(key, value)
}

func (c *context) PutDynamic(key string, valueFN func() interface{}) Context {
	value := &dynval{valueFN}
	c.mx.Lock()
	c.data[key] = value
	c.mx.Unlock()
	return c
}

func (cm *manager) PutGlobal(key string, value interface{}) {
	cm.mxGlobal.Lock()
	cm.global[key] = value
	cm.mxGlobal.Unlock()
}

func (cm *manager) PutGlobalDynamic(key string, valueFN func() interface{}) {
	value := &dynval{valueFN}
	cm.mxGlobal.Lock()
	cm.global[key] = value
	cm.mxGlobal.Unlock()
}

func (c *context) Fill(m Map) {
	for ctx := c; ctx != nil; {
		ctx.mx.RLock()
		fill(m, ctx.data)
		next := ctx.parent
		if next == nil {
			next = ctx.branchedFrom
		}
		ctx.mx.RUnlock()
		ctx = next
	}
}

func (cm *manager) AsMap(obj interface{}, includeGlobals bool) Map {
	return cm.currentContext().asMap(cm, obj, includeGlobals)
}

func (c *context) AsMap(obj interface{}, includeGlobals bool) Map {
	return c.asMap(c.cm, obj, includeGlobals)
}

func (c *context) asMap(cm *manager, obj interface{}, includeGlobals bool) Map {
	result := make(Map, 0)
	cl, ok := obj.(Contextual)
	if ok {
		cl.Fill(result)
	}
	if c != nil {
		c.Fill(result)
	}
	if includeGlobals {
		cm.mxGlobal.RLock()
		fill(result, cm.global)
		cm.mxGlobal.RUnlock()
	}
	return result
}

func (cm *manager) Get(key string) (interface{}, bool) {
	c := cm.currentContext()
	if c != nil {
		return c.Get(key)
	}
	cm.mxGlobal.RLock()
	result, found := cm.global[key]
	cm.mxGlobal.RUnlock()
	return result, found
}

func (c *context) Get(key string) (interface{}, bool) {
	c.mx.RLock()
	result, found := c.data[key]
	c.mx.RUnlock()
	if found {
		return result, found
	}
	if c.parent != nil {
		return c.parent.Get(key)
	}
	c.cm.mxGlobal.Lock()
	result, found = c.cm.global[key]
	c.cm.mxGlobal.Unlock()
	return result, found
}

func fill(m Map, from Map) {
	if m != nil {
		doFill := func(key string, _value interface{}) {
			switch value := _value.(type) {
			case map[string]interface{}:
				for k, v := range value {
					m[k] = v
				}
			default:
				m[key] = value
			}
		}

		for key, value := range from {
			_, alreadyRead := m[key]
			if !alreadyRead {
				switch v := value.(type) {
				case *dynval:
					doFill(key, v.fn())
				default:
					doFill(key, v)
				}
			}
		}
	}
}

func (cm *manager) currentContext() *context {
	id := curGoroutineID()
	cm.mxContexts.RLock()
	c := cm.contexts[id]
	cm.mxContexts.RUnlock()
	return c
}
<|endoftext|>


<commit_before>// Copyright 2018 The LUCI 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 interpreter contains basic skylark interpreter with some features
// that make it useful for non-trivial scripts:
//
//  * Scripts can load other script from the file system.
//  * There's one designated "interpreter root" directory that can be used to
//    load scripts given their path relative to this root. For example,
//    load("//some/script.sky", ...).
//  * Scripts can load protobuf message descriptors (built into the interpreter
//    binary) and instantiate protobuf messages defined there.
//  * Scripts have access to some built-in skylark modules (aka 'stdlib'),
//    supplied by whoever instantiates Interpreter.
//  * All symbols from "init.sky" stdlib module are available globally to all
//    non-stdlib scripts.
//
// Additionally, all script have access to some predefined symbols:
//
//  `proto`, a library with protobuf helpers, see skylarkproto.ProtoLib.
//
//  def struct(**kwargs):
//    """Returns an object resembling namedtuple from Python.
//
//    kwargs will become attributes of the returned object.
//    See also skylarkstruct package.
//
//
//  def fail(msg):
//    """Aborts the script execution with an error message."""
//
//
//  def mutable(value=None):
//    """Returns an object with get and set methods.
//
//    Allows modules to explicitly declare that they wish to keep some
//    mutable (non-frozen) state, which can be modified after the module has
//    loaded (e.g. from an exported function).
//    """
//
//
//  def to_json(value):
//    """Serializes a value to compact JSON.
//
//    Args:
//      value: a skylark value: scalars, lists, tuples, dicts containing only
//        skylark values.
//
//    Returns:
//      A string with its compact JSON serialization.
//    """
package interpreter

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

	"github.com/google/skylark"
	"github.com/google/skylark/skylarkstruct"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/skylark/skylarkproto"
)

// ErrNoStdlibModule should be returned by the stdlib loader function if the
// requested module doesn't exist.
var ErrNoStdlibModule = errors.New("no such stdlib module")

// Interpreter knows how to load skylark scripts that can load other skylark
// scripts, instantiate protobuf messages (with descriptors compiled into the
// interpreter binary) and have access to some built-in standard library.
type Interpreter struct {
	// Root is a path to a root directory with scripts.
	//
	// Scripts will be able to load other scripts from this directory using
	// "//path/rel/to/root" syntax in load(...).
	//
	// Default is ".".
	Root string

	// Predeclared is a dict with predeclared symbols that are available globally.
	//
	// They are available when loading stdlib and when executing user scripts.
	Predeclared skylark.StringDict

	// Usercode knows how to load source code files from the file system.
	//
	// It takes a path relative to Root and returns its content (or an error).
	// Used by ExecFile and by load("<path>") statements inside skylark scripts.
	//
	// The default implementation justs uses io.ReadFile.
	Usercode func(path string) (string, error)

	// Stdlib is a set of scripts that constitute a builtin standard library.
	//
	// It is defined as function that takes a script path and returns its body
	// or ErrNoStdlibModule error if there's no such stdlib module.
	//
	// The stdlib is preloaded before execution of other scripts. The stdlib
	// loading starts with init.sky script that can load other stdlib scripts
	// using load("builtin:<path>", ...).
	//
	// All globals of init.sky script that do not start with '_' will become
	// available as globals in all user scripts.
	Stdlib func(path string) (string, error)

	// Logger is called by skylark's print(...) function.
	//
	// The callback takes the position in the skylark source code where print(...)
	// was called and the message it received.
	//
	// The default implementation just prints the message to stderr.
	Logger func(file string, line int, message string)

	modules map[string]*loadedModule // dicts of loaded modules, keyed by path
	globals skylark.StringDict       // predeclared + symbols from init.sky
}

// loadedModule represents an executed skylark module.
//
// We do not reload modules all the time but rather cache their dicts, just like
// Python.
type loadedModule struct {
	globals skylark.StringDict
	err     error // non-nil if this module could not be loaded
}

// Init initializes the interpreter and loads the stdlib.
//
// Registers most basic built in symbols first (like 'struct' and 'fail'). Then
// executes 'init.sky' from stdlib, which may define more symbols or override
// already defined ones.
// Initializes intr.Usercode and intr.Logger if they are not set.
//
// Whatever symbols end up in the global dict of init.sky stdlib script will
// become available as global symbols in all scripts executed via ExecFile (or
// transitively loaded by them).
func (intr *Interpreter) Init() error {
	if intr.Root == "" {
		intr.Root = "."
	}
	var err error
	if intr.Root, err = filepath.Abs(intr.Root); err != nil {
		return errors.Annotate(err, "failed to resolve %q to an absolute path", intr.Root).Err()
	}

	if intr.Usercode == nil {
		intr.Usercode = func(path string) (string, error) {
			blob, err := ioutil.ReadFile(filepath.Join(intr.Root, path))
			return string(blob), err
		}
	}

	if intr.Logger == nil {
		intr.Logger = func(file string, line int, message string) {
			fmt.Fprintf(os.Stderr, "[%s:%d] %s\n", file, line, message)
		}
	}

	// Register most basic builtin symbols. They'll be available from all scripts
	// (stdlib and user scripts).
	intr.globals = skylark.StringDict{
		"fail":    skylark.NewBuiltin("fail", failImpl),
		"mutable": skylark.NewBuiltin("mutable", mutableImpl),
		"struct":  skylark.NewBuiltin("struct", skylarkstruct.Make),
		"to_json": skylark.NewBuiltin("to_json", toJSONImpl),
	}
	for k, v := range skylarkproto.ProtoLib() {
		intr.globals[k] = v
	}

	// Add all predeclared symbols to make them available when loading stdlib.
	for k, v := range intr.Predeclared {
		intr.globals[k] = v
	}

	// Load the stdlib, if any.
	intr.modules = map[string]*loadedModule{}
	top, err := intr.loadStdlibInit()
	if err != nil && err != ErrNoStdlibModule {
		return err
	}
	for k, v := range top {
		if !strings.HasPrefix(k, "_") {
			intr.globals[k] = v
		}
	}

	return nil
}

// ExecFile executes a skylark script file in an environment that has all
// builtin symbols and all stdlib symbols.
//
// Returns the global dict of the executed script.
func (intr *Interpreter) ExecFile(path string) (skylark.StringDict, error) {
	abs, err := intr.normalizePath(path, "")
	if err != nil {
		return nil, err
	}
	return intr.loadFileModule(abs)
}

// normalizePath converts the path of the module (as it appears in the "load"
// statement) to an absolute file system path or cleaned up "builtin:..." path.
//
// The module path can be specified in two ways:
//   1) As relative to the interpreter root: //path/here/script.sky
//   2) As relative to the current executing script: ../script.sky.
//
// To resolve (2) this function also takes an absolute path to the currently
// executing script. If there's no executing script (e.g. normalizePath is
// called by top-evel ExecFile call), uses current working directory to convert
// 'mod' to an absolute path.
func (intr *Interpreter) normalizePath(mod, cur string) (string, error) {
	// Builtin paths are always relative, so just clean them up.
	if strings.HasPrefix(mod, "builtin:") {
		return "builtin:" + path.Clean(strings.TrimPrefix(mod, "builtin:")), nil
	}

	switch {
	case strings.HasPrefix(mod, "//"):
		// A path relative to the scripts root directory.
		mod = filepath.Join(intr.Root, filepath.FromSlash(strings.TrimLeft(mod, "/")))
	case cur != "":
		// A path relative to the currently executing script.
		mod = filepath.Join(filepath.Dir(cur), filepath.FromSlash(mod))
	default:
		// A path relative to cwd.
		mod = filepath.FromSlash(mod)
	}

	// Make sure we get a nice looking clean path.
	abs, err := filepath.Abs(mod)
	if err != nil {
		return "", errors.Annotate(err, "failed to resolve %q to an absolute path", mod).Err()
	}
	return abs, nil
}

// rootRel converts a path to be relative to the interpreter root.
//
// We give relative paths to skylark.ExecFile so that stack traces look nicer.
func (intr *Interpreter) rootRel(path string) string {
	rel, err := filepath.Rel(intr.Root, path)
	if err != nil {
		panic(fmt.Errorf("failed to resolve %q as relative path to %q", path, intr.Root))
	}
	return rel
}

// thread returns a new skylark.Thread to use for executing a single file.
//
// We do not reuse threads between files. All global state is passed through
// intr.globals and intr.modules.
func (intr *Interpreter) thread() *skylark.Thread {
	return &skylark.Thread{
		Load: intr.loadImpl,
		Print: func(th *skylark.Thread, msg string) {
			position := th.Caller().Position()
			intr.Logger(position.Filename(), int(position.Line), msg)
		},
	}
}

// loadIfMissing loads the module by calling the given callback if the module
// hasn't been loaded before or just returns the existing module dict otherwise.
func (intr *Interpreter) loadIfMissing(key string, loader func() (skylark.StringDict, error)) (skylark.StringDict, error) {
	switch m, ok := intr.modules[key]; {
	case m != nil: // already loaded or attempted to be loaded
		return m.globals, m.err
	case ok: // this module is being loaded right now
		return nil, errors.New("cycle in load graph")
	}

	// Add a placeholder to indicate we are loading this module to detect cycles.
	intr.modules[key] = nil

	m := &loadedModule{
		err: fmt.Errorf("panic when loading %q", key), // overwritten on non-panic
	}
	defer func() { intr.modules[key] = m }()

	m.globals, m.err = loader()
	return m.globals, m.err
}

// loadImpl implements skylark's load(...) builtin.
//
// It understands 3 kinds of modules:
//  1) A module from the file system referenced either via a path relative to
//     the interpreter root ("//a/b/c.sky") or relative to the currently
//     executing script ("../a/b/c.sky").
//  2) A protobuf file (compiled into the interpreter binary), referenced by
//     the location of the proto file in the protobuf lib registry:
//        "builtin:go.chromium.org/luci/.../file.proto"
//  3) An stdlib module, as supplied by Stdlib callback:
//        "builtin:some/path/to/be/passed/to/the/callback.sky"
func (intr *Interpreter) loadImpl(thread *skylark.Thread, module string) (skylark.StringDict, error) {
	// This would be either a "builtin:..." path or a path relative to the root,
	// since that's what we pass to skylark.ExecFile.
	cur := thread.Caller().Position().Filename()

	// Convert it back to an absolute path, as required by normalizePath.
	curIsBuiltin := strings.HasPrefix(cur, "builtin:")
	if !curIsBuiltin {
		cur = filepath.Join(intr.Root, cur)
	}

	// Cleanup and normalize the path to the module being loaded. 'module' here
	// will be either a "builtin:..." path or an absolute file system path.
	module, err := intr.normalizePath(module, cur)
	if err != nil {
		return nil, err
	}

	// Builtin scripts can load only other builtin scripts, not something from the
	// filesystem.
	loadingBuiltin := strings.HasPrefix(module, "builtin:")
	if curIsBuiltin && !loadingBuiltin {
		return nil, errors.Reason(
			"builtin module %q is attempting to load non-builtin %q, this is forbidden", cur, module).Err()
	}

	// Actually load the module if it hasn't been loaded before.
	return intr.loadIfMissing(module, func() (skylark.StringDict, error) {
		if loadingBuiltin {
			return intr.loadBuiltinModule(module)
		}
		return intr.loadFileModule(module)
	})
}

// loadBuiltinModule loads a builtin module, given as "builtin:<path>".
//
// It can be either a proto descriptor (compiled into the binary) or a stdlib
// module (as supplied by Stdlib callback).
//
// Returns ErrNoStdlibModule if there's no such stdlib module.
func (intr *Interpreter) loadBuiltinModule(module string) (skylark.StringDict, error) {
	path := strings.TrimPrefix(module, "builtin:")
	if strings.HasSuffix(path, ".proto") {
		return skylarkproto.LoadProtoModule(path)
	}
	if intr.Stdlib == nil {
		return nil, ErrNoStdlibModule
	}
	src, err := intr.Stdlib(path)
	if err != nil {
		return nil, err
	}
	return skylark.ExecFile(intr.thread(), module, src, intr.globals)
}

// loadStdlibInit loads init.sky from the stdlib and returns its global dict.
//
// Returns ErrNoStdlibModule if there's no init.sky in the stdlib.
func (intr *Interpreter) loadStdlibInit() (skylark.StringDict, error) {
	const initSky = "builtin:init.sky"
	return intr.loadIfMissing(initSky, func() (skylark.StringDict, error) {
		return intr.loadBuiltinModule(initSky)
	})
}

// loadFileModule loads a skylark module from the file system.
//
// 'path' must always be absolute here, per normalizePath output.
func (intr *Interpreter) loadFileModule(path string) (skylark.StringDict, error) {
	path = intr.rootRel(path)
	src, err := intr.Usercode(path)
	if err != nil {
		return nil, errors.Annotate(err, "failed to read %q", path).Err()
	}
	return skylark.ExecFile(intr.thread(), path, src, intr.globals)
}
<commit_msg>[skylark] Fix panic after rolling deps.<commit_after>// Copyright 2018 The LUCI 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 interpreter contains basic skylark interpreter with some features
// that make it useful for non-trivial scripts:
//
//  * Scripts can load other script from the file system.
//  * There's one designated "interpreter root" directory that can be used to
//    load scripts given their path relative to this root. For example,
//    load("//some/script.sky", ...).
//  * Scripts can load protobuf message descriptors (built into the interpreter
//    binary) and instantiate protobuf messages defined there.
//  * Scripts have access to some built-in skylark modules (aka 'stdlib'),
//    supplied by whoever instantiates Interpreter.
//  * All symbols from "init.sky" stdlib module are available globally to all
//    non-stdlib scripts.
//
// Additionally, all script have access to some predefined symbols:
//
//  `proto`, a library with protobuf helpers, see skylarkproto.ProtoLib.
//
//  def struct(**kwargs):
//    """Returns an object resembling namedtuple from Python.
//
//    kwargs will become attributes of the returned object.
//    See also skylarkstruct package.
//
//
//  def fail(msg):
//    """Aborts the script execution with an error message."""
//
//
//  def mutable(value=None):
//    """Returns an object with get and set methods.
//
//    Allows modules to explicitly declare that they wish to keep some
//    mutable (non-frozen) state, which can be modified after the module has
//    loaded (e.g. from an exported function).
//    """
//
//
//  def to_json(value):
//    """Serializes a value to compact JSON.
//
//    Args:
//      value: a skylark value: scalars, lists, tuples, dicts containing only
//        skylark values.
//
//    Returns:
//      A string with its compact JSON serialization.
//    """
package interpreter

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

	"github.com/google/skylark"
	"github.com/google/skylark/skylarkstruct"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/skylark/skylarkproto"
)

// ErrNoStdlibModule should be returned by the stdlib loader function if the
// requested module doesn't exist.
var ErrNoStdlibModule = errors.New("no such stdlib module")

// Interpreter knows how to load skylark scripts that can load other skylark
// scripts, instantiate protobuf messages (with descriptors compiled into the
// interpreter binary) and have access to some built-in standard library.
type Interpreter struct {
	// Root is a path to a root directory with scripts.
	//
	// Scripts will be able to load other scripts from this directory using
	// "//path/rel/to/root" syntax in load(...).
	//
	// Default is ".".
	Root string

	// Predeclared is a dict with predeclared symbols that are available globally.
	//
	// They are available when loading stdlib and when executing user scripts.
	Predeclared skylark.StringDict

	// Usercode knows how to load source code files from the file system.
	//
	// It takes a path relative to Root and returns its content (or an error).
	// Used by ExecFile and by load("<path>") statements inside skylark scripts.
	//
	// The default implementation justs uses io.ReadFile.
	Usercode func(path string) (string, error)

	// Stdlib is a set of scripts that constitute a builtin standard library.
	//
	// It is defined as function that takes a script path and returns its body
	// or ErrNoStdlibModule error if there's no such stdlib module.
	//
	// The stdlib is preloaded before execution of other scripts. The stdlib
	// loading starts with init.sky script that can load other stdlib scripts
	// using load("builtin:<path>", ...).
	//
	// All globals of init.sky script that do not start with '_' will become
	// available as globals in all user scripts.
	Stdlib func(path string) (string, error)

	// Logger is called by skylark's print(...) function.
	//
	// The callback takes the position in the skylark source code where print(...)
	// was called and the message it received.
	//
	// The default implementation just prints the message to stderr.
	Logger func(file string, line int, message string)

	modules map[string]*loadedModule // dicts of loaded modules, keyed by path
	globals skylark.StringDict       // predeclared + symbols from init.sky
}

// loadedModule represents an executed skylark module.
//
// We do not reload modules all the time but rather cache their dicts, just like
// Python.
type loadedModule struct {
	globals skylark.StringDict
	err     error // non-nil if this module could not be loaded
}

// Init initializes the interpreter and loads the stdlib.
//
// Registers most basic built in symbols first (like 'struct' and 'fail'). Then
// executes 'init.sky' from stdlib, which may define more symbols or override
// already defined ones.
// Initializes intr.Usercode and intr.Logger if they are not set.
//
// Whatever symbols end up in the global dict of init.sky stdlib script will
// become available as global symbols in all scripts executed via ExecFile (or
// transitively loaded by them).
func (intr *Interpreter) Init() error {
	if intr.Root == "" {
		intr.Root = "."
	}
	var err error
	if intr.Root, err = filepath.Abs(intr.Root); err != nil {
		return errors.Annotate(err, "failed to resolve %q to an absolute path", intr.Root).Err()
	}

	if intr.Usercode == nil {
		intr.Usercode = func(path string) (string, error) {
			blob, err := ioutil.ReadFile(filepath.Join(intr.Root, path))
			return string(blob), err
		}
	}

	if intr.Logger == nil {
		intr.Logger = func(file string, line int, message string) {
			fmt.Fprintf(os.Stderr, "[%s:%d] %s\n", file, line, message)
		}
	}

	// Register most basic builtin symbols. They'll be available from all scripts
	// (stdlib and user scripts).
	intr.globals = skylark.StringDict{
		"fail":    skylark.NewBuiltin("fail", failImpl),
		"mutable": skylark.NewBuiltin("mutable", mutableImpl),
		"struct":  skylark.NewBuiltin("struct", skylarkstruct.Make),
		"to_json": skylark.NewBuiltin("to_json", toJSONImpl),
	}
	for k, v := range skylarkproto.ProtoLib() {
		intr.globals[k] = v
	}

	// Add all predeclared symbols to make them available when loading stdlib.
	for k, v := range intr.Predeclared {
		intr.globals[k] = v
	}

	// Load the stdlib, if any.
	intr.modules = map[string]*loadedModule{}
	top, err := intr.loadStdlibInit()
	if err != nil && err != ErrNoStdlibModule {
		return err
	}
	for k, v := range top {
		if !strings.HasPrefix(k, "_") {
			intr.globals[k] = v
		}
	}

	return nil
}

// ExecFile executes a skylark script file in an environment that has all
// builtin symbols and all stdlib symbols.
//
// Returns the global dict of the executed script.
func (intr *Interpreter) ExecFile(path string) (skylark.StringDict, error) {
	abs, err := intr.normalizePath(path, "")
	if err != nil {
		return nil, err
	}
	return intr.loadFileModule(abs)
}

// normalizePath converts the path of the module (as it appears in the "load"
// statement) to an absolute file system path or cleaned up "builtin:..." path.
//
// The module path can be specified in two ways:
//   1) As relative to the interpreter root: //path/here/script.sky
//   2) As relative to the current executing script: ../script.sky.
//
// To resolve (2) this function also takes an absolute path to the currently
// executing script. If there's no executing script (e.g. normalizePath is
// called by top-evel ExecFile call), uses current working directory to convert
// 'mod' to an absolute path.
func (intr *Interpreter) normalizePath(mod, cur string) (string, error) {
	// Builtin paths are always relative, so just clean them up.
	if strings.HasPrefix(mod, "builtin:") {
		return "builtin:" + path.Clean(strings.TrimPrefix(mod, "builtin:")), nil
	}

	switch {
	case strings.HasPrefix(mod, "//"):
		// A path relative to the scripts root directory.
		mod = filepath.Join(intr.Root, filepath.FromSlash(strings.TrimLeft(mod, "/")))
	case cur != "":
		// A path relative to the currently executing script.
		mod = filepath.Join(filepath.Dir(cur), filepath.FromSlash(mod))
	default:
		// A path relative to cwd.
		mod = filepath.FromSlash(mod)
	}

	// Make sure we get a nice looking clean path.
	abs, err := filepath.Abs(mod)
	if err != nil {
		return "", errors.Annotate(err, "failed to resolve %q to an absolute path", mod).Err()
	}
	return abs, nil
}

// rootRel converts a path to be relative to the interpreter root.
//
// We give relative paths to skylark.ExecFile so that stack traces look nicer.
func (intr *Interpreter) rootRel(path string) string {
	rel, err := filepath.Rel(intr.Root, path)
	if err != nil {
		panic(fmt.Errorf("failed to resolve %q as relative path to %q", path, intr.Root))
	}
	return rel
}

// thread returns a new skylark.Thread to use for executing a single file.
//
// We do not reuse threads between files. All global state is passed through
// intr.globals and intr.modules.
func (intr *Interpreter) thread() *skylark.Thread {
	return &skylark.Thread{
		Load: intr.loadImpl,
		Print: func(th *skylark.Thread, msg string) {
			position := th.Caller().Position()
			intr.Logger(position.Filename(), int(position.Line), msg)
		},
	}
}

// loadIfMissing loads the module by calling the given callback if the module
// hasn't been loaded before or just returns the existing module dict otherwise.
func (intr *Interpreter) loadIfMissing(key string, loader func() (skylark.StringDict, error)) (skylark.StringDict, error) {
	switch m, ok := intr.modules[key]; {
	case m != nil: // already loaded or attempted to be loaded
		return m.globals, m.err
	case ok: // this module is being loaded right now
		return nil, errors.New("cycle in load graph")
	}

	// Add a placeholder to indicate we are loading this module to detect cycles.
	intr.modules[key] = nil

	m := &loadedModule{
		err: fmt.Errorf("panic when loading %q", key), // overwritten on non-panic
	}
	defer func() { intr.modules[key] = m }()

	m.globals, m.err = loader()
	return m.globals, m.err
}

// loadImpl implements skylark's load(...) builtin.
//
// It understands 3 kinds of modules:
//  1) A module from the file system referenced either via a path relative to
//     the interpreter root ("//a/b/c.sky") or relative to the currently
//     executing script ("../a/b/c.sky").
//  2) A protobuf file (compiled into the interpreter binary), referenced by
//     the location of the proto file in the protobuf lib registry:
//        "builtin:go.chromium.org/luci/.../file.proto"
//  3) An stdlib module, as supplied by Stdlib callback:
//        "builtin:some/path/to/be/passed/to/the/callback.sky"
func (intr *Interpreter) loadImpl(thread *skylark.Thread, module string) (skylark.StringDict, error) {
	// Grab a name of a module that is calling load(...). This would be either a
	// "builtin:..." path or a path relative to the root, since that's what we
	// pass to skylark.ExecFile.
	cur := thread.TopFrame().Position().Filename()

	// Convert it back to an absolute path, as required by normalizePath.
	curIsBuiltin := strings.HasPrefix(cur, "builtin:")
	if !curIsBuiltin {
		cur = filepath.Join(intr.Root, cur)
	}

	// Cleanup and normalize the path to the module being loaded. 'module' here
	// will be either a "builtin:..." path or an absolute file system path.
	module, err := intr.normalizePath(module, cur)
	if err != nil {
		return nil, err
	}

	// Builtin scripts can load only other builtin scripts, not something from the
	// filesystem.
	loadingBuiltin := strings.HasPrefix(module, "builtin:")
	if curIsBuiltin && !loadingBuiltin {
		return nil, errors.Reason(
			"builtin module %q is attempting to load non-builtin %q, this is forbidden", cur, module).Err()
	}

	// Actually load the module if it hasn't been loaded before.
	return intr.loadIfMissing(module, func() (skylark.StringDict, error) {
		if loadingBuiltin {
			return intr.loadBuiltinModule(module)
		}
		return intr.loadFileModule(module)
	})
}

// loadBuiltinModule loads a builtin module, given as "builtin:<path>".
//
// It can be either a proto descriptor (compiled into the binary) or a stdlib
// module (as supplied by Stdlib callback).
//
// Returns ErrNoStdlibModule if there's no such stdlib module.
func (intr *Interpreter) loadBuiltinModule(module string) (skylark.StringDict, error) {
	path := strings.TrimPrefix(module, "builtin:")
	if strings.HasSuffix(path, ".proto") {
		return skylarkproto.LoadProtoModule(path)
	}
	if intr.Stdlib == nil {
		return nil, ErrNoStdlibModule
	}
	src, err := intr.Stdlib(path)
	if err != nil {
		return nil, err
	}
	return skylark.ExecFile(intr.thread(), module, src, intr.globals)
}

// loadStdlibInit loads init.sky from the stdlib and returns its global dict.
//
// Returns ErrNoStdlibModule if there's no init.sky in the stdlib.
func (intr *Interpreter) loadStdlibInit() (skylark.StringDict, error) {
	const initSky = "builtin:init.sky"
	return intr.loadIfMissing(initSky, func() (skylark.StringDict, error) {
		return intr.loadBuiltinModule(initSky)
	})
}

// loadFileModule loads a skylark module from the file system.
//
// 'path' must always be absolute here, per normalizePath output.
func (intr *Interpreter) loadFileModule(path string) (skylark.StringDict, error) {
	path = intr.rootRel(path)
	src, err := intr.Usercode(path)
	if err != nil {
		return nil, errors.Annotate(err, "failed to read %q", path).Err()
	}
	return skylark.ExecFile(intr.thread(), path, src, intr.globals)
}
<|endoftext|>


<commit_before>// GoMySQL - A MySQL client library for Go
//
// Copyright 2010-2011 Phil Bayfield. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mysql

import (
	"math"
	"os"
	"strconv"
)

// bytes to int
func btoi(b []byte) int {
	return int(btoui(b))
}

// int to bytes
func itob(n int) []byte {
	return uitob(uint(n))
}

// bytes to uint
func btoui(b []byte) (n uint) {
	for i := uint8(0); i < uint8(strconv.IntSize)/8; i++ {
		n |= uint(b[i]) << (i * 8)
	}
	return
}

// uint to bytes
func uitob(n uint) (b []byte) {
	b = make([]byte, strconv.IntSize/8)
	for i := uint8(0); i < uint8(strconv.IntSize)/8; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}

// bytes to int16
func btoi16(b []byte) int16 {
	return int16(btoui16(b))
}

// int16 to bytes
func i16tob(n int16) []byte {
	return ui16tob(uint16(n))
}

// bytes to uint16
func btoui16(b []byte) (n uint16) {
	n |= uint16(b[0])
	n |= uint16(b[1]) << 8
	return
}

// uint16 to bytes
func ui16tob(n uint16) (b []byte) {
	b = make([]byte, 2)
	b[0] = byte(n)
	b[1] = byte(n >> 8)
	return
}

// bytes to int24
func btoi24(b []byte) (n int32) {
	u := btoui24(b)
	if u&0x800000 != 0 {
		u |= 0xff000000
	}
	n = int32(u)
	return
}

// int24 to bytes
func i24tob(n int32) []byte {
	return ui24tob(uint32(n))
}

// bytes to uint24
func btoui24(b []byte) (n uint32) {
	for i := uint8(0); i < 3; i++ {
		n |= uint32(b[i]) << (i * 8)
	}
	return
}

// uint24 to bytes
func ui24tob(n uint32) (b []byte) {
	b = make([]byte, 3)
	for i := uint8(0); i < 3; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}

// bytes to int32
func btoi32(b []byte) int32 {
	return int32(btoui32(b))
}

// int32 to bytes
func i32tob(n int32) []byte {
	return ui32tob(uint32(n))
}

// bytes to uint32
func btoui32(b []byte) (n uint32) {
	for i := uint8(0); i < 4; i++ {
		n |= uint32(b[i]) << (i * 8)
	}
	return
}

// uint32 to bytes
func ui32tob(n uint32) (b []byte) {
	b = make([]byte, 4)
	for i := uint8(0); i < 4; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}
// bytes to int64
func btoi64(b []byte) int64 {
	return int64(btoui64(b))
}

// int64 to bytes
func i64tob(n int64) []byte {
	return ui64tob(uint64(n))
}

// bytes to uint64
func btoui64(b []byte) (n uint64) {
	for i := uint8(0); i < 8; i++ {
		n |= uint64(b[i]) << (i * 8)
	}
	return
}

// uint64 to bytes
func ui64tob(n uint64) (b []byte) {
	b = make([]byte, 8)
	for i := uint8(0); i < 8; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}

// bytes to float32
func btof32(b []byte) float32 {
	return math.Float32frombits(btoui32(b))
}

// float32 to bytes
func f32tob(f float32) []byte {
	return ui32tob(math.Float32bits(f))
}

// bytes to float64
func btof64(b []byte) float64 {
	return math.Float64frombits(btoui64(b))
}

// float64 to bytes
func f64tob(f float64) []byte {
	return ui64tob(math.Float64bits(f))
}

// bytes to length
func btolcb(b []byte) (num uint64, n int, err os.Error) {
	switch {
	// 0-250 = value of first byte
	case b[0] <= 250:
		num = uint64(b[0])
		n = 1
		return
	// 251 column value = NULL
	case b[0] == 251:
		num = 0
		n = 1
		return
	// 252 following 2 = value of following 16-bit word
	case b[0] == 252:
		n = 3
	// 253 following 3 = value of following 24-bit word
	case b[0] == 253:
		n = 4
	// 254 following 8 = value of following 64-bit word
	case b[0] == 254:
		n = 9
	}
	// Check there are enough bytes
	if len(b) < n {
		err = os.EOF
		return
	}
	// Get uint64
	t := make([]byte, 8)
	copy(t, b[1:n])
	num = btoui64(t)
	return
}

// length to bytes
func lcbtob(n uint64) (b []byte) {
	switch {
	// <= 250 = 1 byte
	case n <= 250:
		b = []byte{byte(n)}
	// <= 0xffff = 252 + 2 bytes
	case n <= 0xffff:
		b = []byte{0xfc, byte(n), byte(n >> 8)}
	// <= 0xffffff = 253 + 3 bytes
	case n <= 0xffffff:
		b = []byte{0xfd, byte(n), byte(n >> 8), byte(n >> 16)}
		// Due to max packet size the 8 byte version is never actually used so is ommited
	}
	return
}

// any to uint64
func atou64(i interface{}) (n uint64) {
	switch t := i.(type) {
	case int:
		n = uint64(t)
	case uint:
		n = uint64(t)
	case int8:
		n = uint64(t)
	case uint8:
		n = uint64(t)
	case int16:
		n = uint64(t)
	case uint16:
		n = uint64(t)
	case int32:
		n = uint64(t)
	case uint32:
		n = uint64(t)
	case int64:
		n = uint64(t)
	case uint64:
		return t
	default:
		panic("Not a numeric type")
	}
	return
}

// any to float64
func atof64(i interface{}) (f float64) {
	switch t := i.(type) {
	case float32:
		f = float64(t)
	case float64:
		return t
	default:
		panic("Not a floating point type")
	}
	return
}

// any to string
func atos(i interface{}) (s string) {
	switch t := i.(type) {
	case []byte:
		s = string(t)
	case string:
		return t
	default:
		panic("Not a string or compatible type")
	}
	return
}
<commit_msg>added more conversion options for binding statement results<commit_after>// GoMySQL - A MySQL client library for Go
//
// Copyright 2010-2011 Phil Bayfield. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mysql

import (
	"math"
	"os"
	"strconv"
)

// bytes to int
func btoi(b []byte) int {
	return int(btoui(b))
}

// int to bytes
func itob(n int) []byte {
	return uitob(uint(n))
}

// bytes to uint
func btoui(b []byte) (n uint) {
	for i := uint8(0); i < uint8(strconv.IntSize)/8; i++ {
		n |= uint(b[i]) << (i * 8)
	}
	return
}

// uint to bytes
func uitob(n uint) (b []byte) {
	b = make([]byte, strconv.IntSize/8)
	for i := uint8(0); i < uint8(strconv.IntSize)/8; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}

// bytes to int16
func btoi16(b []byte) int16 {
	return int16(btoui16(b))
}

// int16 to bytes
func i16tob(n int16) []byte {
	return ui16tob(uint16(n))
}

// bytes to uint16
func btoui16(b []byte) (n uint16) {
	n |= uint16(b[0])
	n |= uint16(b[1]) << 8
	return
}

// uint16 to bytes
func ui16tob(n uint16) (b []byte) {
	b = make([]byte, 2)
	b[0] = byte(n)
	b[1] = byte(n >> 8)
	return
}

// bytes to int24
func btoi24(b []byte) (n int32) {
	u := btoui24(b)
	if u&0x800000 != 0 {
		u |= 0xff000000
	}
	n = int32(u)
	return
}

// int24 to bytes
func i24tob(n int32) []byte {
	return ui24tob(uint32(n))
}

// bytes to uint24
func btoui24(b []byte) (n uint32) {
	for i := uint8(0); i < 3; i++ {
		n |= uint32(b[i]) << (i * 8)
	}
	return
}

// uint24 to bytes
func ui24tob(n uint32) (b []byte) {
	b = make([]byte, 3)
	for i := uint8(0); i < 3; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}

// bytes to int32
func btoi32(b []byte) int32 {
	return int32(btoui32(b))
}

// int32 to bytes
func i32tob(n int32) []byte {
	return ui32tob(uint32(n))
}

// bytes to uint32
func btoui32(b []byte) (n uint32) {
	for i := uint8(0); i < 4; i++ {
		n |= uint32(b[i]) << (i * 8)
	}
	return
}

// uint32 to bytes
func ui32tob(n uint32) (b []byte) {
	b = make([]byte, 4)
	for i := uint8(0); i < 4; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}
// bytes to int64
func btoi64(b []byte) int64 {
	return int64(btoui64(b))
}

// int64 to bytes
func i64tob(n int64) []byte {
	return ui64tob(uint64(n))
}

// bytes to uint64
func btoui64(b []byte) (n uint64) {
	for i := uint8(0); i < 8; i++ {
		n |= uint64(b[i]) << (i * 8)
	}
	return
}

// uint64 to bytes
func ui64tob(n uint64) (b []byte) {
	b = make([]byte, 8)
	for i := uint8(0); i < 8; i++ {
		b[i] = byte(n >> (i * 8))
	}
	return
}

// bytes to float32
func btof32(b []byte) float32 {
	return math.Float32frombits(btoui32(b))
}

// float32 to bytes
func f32tob(f float32) []byte {
	return ui32tob(math.Float32bits(f))
}

// bytes to float64
func btof64(b []byte) float64 {
	return math.Float64frombits(btoui64(b))
}

// float64 to bytes
func f64tob(f float64) []byte {
	return ui64tob(math.Float64bits(f))
}

// bytes to length
func btolcb(b []byte) (num uint64, n int, err os.Error) {
	switch {
	// 0-250 = value of first byte
	case b[0] <= 250:
		num = uint64(b[0])
		n = 1
		return
	// 251 column value = NULL
	case b[0] == 251:
		num = 0
		n = 1
		return
	// 252 following 2 = value of following 16-bit word
	case b[0] == 252:
		n = 3
	// 253 following 3 = value of following 24-bit word
	case b[0] == 253:
		n = 4
	// 254 following 8 = value of following 64-bit word
	case b[0] == 254:
		n = 9
	}
	// Check there are enough bytes
	if len(b) < n {
		err = os.EOF
		return
	}
	// Get uint64
	t := make([]byte, 8)
	copy(t, b[1:n])
	num = btoui64(t)
	return
}

// length to bytes
func lcbtob(n uint64) (b []byte) {
	switch {
	// <= 250 = 1 byte
	case n <= 250:
		b = []byte{byte(n)}
	// <= 0xffff = 252 + 2 bytes
	case n <= 0xffff:
		b = []byte{0xfc, byte(n), byte(n >> 8)}
	// <= 0xffffff = 253 + 3 bytes
	case n <= 0xffffff:
		b = []byte{0xfd, byte(n), byte(n >> 8), byte(n >> 16)}
		// Due to max packet size the 8 byte version is never actually used so is ommited
	}
	return
}

// any to uint64
func atou64(i interface{}) (n uint64) {
	switch t := i.(type) {
	case int:
		n = uint64(t)
	case uint:
		n = uint64(t)
	case int8:
		n = uint64(t)
	case uint8:
		n = uint64(t)
	case int16:
		n = uint64(t)
	case uint16:
		n = uint64(t)
	case int32:
		n = uint64(t)
	case uint32:
		n = uint64(t)
	case int64:
		n = uint64(t)
	case uint64:
		return t
	case string:
		// Convert to int64 first for signing bit
		in, err := strconv.Atoi64(t)
		if err != nil {
			panic("Invalid string for integer conversion")
		}
		n = uint64(in)
	default:
		panic("Not a numeric type")
	}
	return
}

// any to float64
func atof64(i interface{}) (f float64) {
	switch t := i.(type) {
	case float32:
		f = float64(t)
	case float64:
		return t
	case string:
		var err os.Error
		f, err = strconv.Atof64(t)
		if err != nil {
			panic("Invalid string for floating point conversion")
		}
	default:
		panic("Not a floating point type")
	}
	return
}

// any to string
func atos(i interface{}) (s string) {
	switch t := i.(type) {
	case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
		s = strconv.Uitoa64(atou64(i))
	case float32:
		s = strconv.Ftoa32(t, 'f', -1)
	case float64:
		s = strconv.Ftoa64(t, 'f', -1)
	case []byte:
		s = string(t)
	case string:
		return t
	default:
		panic("Not a string or compatible type")
	}
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 options

import (
	"fmt"
	"net"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apiserver/pkg/server"
	utilfeature "k8s.io/apiserver/pkg/util/feature"

	// add the generic feature gates
	"k8s.io/apiserver/pkg/features"

	"github.com/spf13/pflag"
)

// ServerRunOptions contains the options while running a generic api server.
type ServerRunOptions struct {
	AdvertiseAddress net.IP

	CorsAllowedOriginList       []string
	ExternalHost                string
	MaxRequestsInFlight         int
	MaxMutatingRequestsInFlight int
	RequestTimeout              time.Duration
	LivezGracePeriod            time.Duration
	MinRequestTimeout           int
	ShutdownDelayDuration       time.Duration
	// We intentionally did not add a flag for this option. Users of the
	// apiserver library can wire it to a flag.
	JSONPatchMaxCopyBytes int64
	// The limit on the request body size that would be accepted and
	// decoded in a write request. 0 means no limit.
	// We intentionally did not add a flag for this option. Users of the
	// apiserver library can wire it to a flag.
	MaxRequestBodyBytes        int64
	TargetRAMMB                int
	EnableInflightQuotaHandler bool
}

func NewServerRunOptions() *ServerRunOptions {
	defaults := server.NewConfig(serializer.CodecFactory{})
	return &ServerRunOptions{
		MaxRequestsInFlight:         defaults.MaxRequestsInFlight,
		MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
		RequestTimeout:              defaults.RequestTimeout,
		LivezGracePeriod:            defaults.LivezGracePeriod,
		MinRequestTimeout:           defaults.MinRequestTimeout,
		ShutdownDelayDuration:       defaults.ShutdownDelayDuration,
		JSONPatchMaxCopyBytes:       defaults.JSONPatchMaxCopyBytes,
		MaxRequestBodyBytes:         defaults.MaxRequestBodyBytes,
	}
}

// ApplyOptions applies the run options to the method receiver and returns self
func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
	c.CorsAllowedOriginList = s.CorsAllowedOriginList
	c.ExternalAddress = s.ExternalHost
	c.MaxRequestsInFlight = s.MaxRequestsInFlight
	c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
	c.LivezGracePeriod = s.LivezGracePeriod
	c.RequestTimeout = s.RequestTimeout
	c.MinRequestTimeout = s.MinRequestTimeout
	c.ShutdownDelayDuration = s.ShutdownDelayDuration
	c.JSONPatchMaxCopyBytes = s.JSONPatchMaxCopyBytes
	c.MaxRequestBodyBytes = s.MaxRequestBodyBytes
	c.PublicAddress = s.AdvertiseAddress

	return nil
}

// DefaultAdvertiseAddress sets the field AdvertiseAddress if unset. The field will be set based on the SecureServingOptions.
func (s *ServerRunOptions) DefaultAdvertiseAddress(secure *SecureServingOptions) error {
	if secure == nil {
		return nil
	}

	if s.AdvertiseAddress == nil || s.AdvertiseAddress.IsUnspecified() {
		hostIP, err := secure.DefaultExternalAddress()
		if err != nil {
			return fmt.Errorf("Unable to find suitable network address.error='%v'. "+
				"Try to set the AdvertiseAddress directly or provide a valid BindAddress to fix this.", err)
		}
		s.AdvertiseAddress = hostIP
	}

	return nil
}

// Validate checks validation of ServerRunOptions
func (s *ServerRunOptions) Validate() []error {
	errors := []error{}
	if s.TargetRAMMB < 0 {
		errors = append(errors, fmt.Errorf("--target-ram-mb can not be negative value"))
	}

	if s.LivezGracePeriod < 0 {
		errors = append(errors, fmt.Errorf("--livez-grace-period can not be a negative value"))
	}

	if s.EnableInflightQuotaHandler {
		if !utilfeature.DefaultFeatureGate.Enabled(features.RequestManagement) {
			errors = append(errors, fmt.Errorf("--enable-inflight-quota-handler can not be set if feature "+
				"gate RequestManagement is disabled"))
		}
		if s.MaxMutatingRequestsInFlight != 0 {
			errors = append(errors, fmt.Errorf("--max-mutating-requests-inflight=%v "+
				"can not be set if enabled inflight quota handler", s.MaxMutatingRequestsInFlight))
		}
		if s.MaxRequestsInFlight != 0 {
			errors = append(errors, fmt.Errorf("--max-requests-inflight=%v "+
				"can not be set if enabled inflight quota handler", s.MaxRequestsInFlight))
		}
	} else {
		if s.MaxRequestsInFlight < 0 {
			errors = append(errors, fmt.Errorf("--max-requests-inflight can not be negative value"))
		}
		if s.MaxMutatingRequestsInFlight < 0 {
			errors = append(errors, fmt.Errorf("--max-mutating-requests-inflight can not be negative value"))
		}
	}

	if s.RequestTimeout.Nanoseconds() < 0 {
		errors = append(errors, fmt.Errorf("--request-timeout can not be negative value"))
	}

	if s.MinRequestTimeout < 0 {
		errors = append(errors, fmt.Errorf("--min-request-timeout can not be negative value"))
	}

	if s.ShutdownDelayDuration < 0 {
		errors = append(errors, fmt.Errorf("--shutdown-delay-duration can not be negative value"))
	}

	if s.JSONPatchMaxCopyBytes < 0 {
		errors = append(errors, fmt.Errorf("--json-patch-max-copy-bytes can not be negative value"))
	}

	if s.MaxRequestBodyBytes < 0 {
		errors = append(errors, fmt.Errorf("--max-resource-write-bytes can not be negative value"))
	}

	return errors
}

// AddUniversalFlags adds flags for a specific APIServer to the specified FlagSet
func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
	// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
	// arrange these text blocks sensibly. Grrr.

	fs.IPVar(&s.AdvertiseAddress, "advertise-address", s.AdvertiseAddress, ""+
		"The IP address on which to advertise the apiserver to members of the cluster. This "+
		"address must be reachable by the rest of the cluster. If blank, the --bind-address "+
		"will be used. If --bind-address is unspecified, the host's default interface will "+
		"be used.")

	fs.StringSliceVar(&s.CorsAllowedOriginList, "cors-allowed-origins", s.CorsAllowedOriginList, ""+
		"List of allowed origins for CORS, comma separated.  An allowed origin can be a regular "+
		"expression to support subdomain matching. If this list is empty CORS will not be enabled.")

	fs.IntVar(&s.TargetRAMMB, "target-ram-mb", s.TargetRAMMB,
		"Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")

	fs.StringVar(&s.ExternalHost, "external-hostname", s.ExternalHost,
		"The hostname to use when generating externalized URLs for this master (e.g. Swagger API Docs).")

	deprecatedMasterServiceNamespace := metav1.NamespaceDefault
	fs.StringVar(&deprecatedMasterServiceNamespace, "master-service-namespace", deprecatedMasterServiceNamespace, ""+
		"DEPRECATED: the namespace from which the kubernetes master services should be injected into pods.")

	fs.IntVar(&s.MaxRequestsInFlight, "max-requests-inflight", s.MaxRequestsInFlight, ""+
		"The maximum number of non-mutating requests in flight at a given time. When the server exceeds this, "+
		"it rejects requests. Zero for no limit.")

	fs.IntVar(&s.MaxMutatingRequestsInFlight, "max-mutating-requests-inflight", s.MaxMutatingRequestsInFlight, ""+
		"The maximum number of mutating requests in flight at a given time. When the server exceeds this, "+
		"it rejects requests. Zero for no limit.")

	fs.DurationVar(&s.RequestTimeout, "request-timeout", s.RequestTimeout, ""+
		"An optional field indicating the duration a handler must keep a request open before timing "+
		"it out. This is the default request timeout for requests but may be overridden by flags such as "+
		"--min-request-timeout for specific types of requests.")

	fs.DurationVar(&s.LivezGracePeriod, "livez-grace-period", s.LivezGracePeriod, ""+
		"This option represents the maximum amount of time it should take for apiserver to complete its startup sequence "+
		"and become live. From apiserver's start time to when this amount of time has elapsed, /livez will assume "+
		"that unfinished post-start hooks will complete successfully and therefore return true.")

	fs.IntVar(&s.MinRequestTimeout, "min-request-timeout", s.MinRequestTimeout, ""+
		"An optional field indicating the minimum number of seconds a handler must keep "+
		"a request open before timing it out. Currently only honored by the watch request "+
		"handler, which picks a randomized value above this number as the connection timeout, "+
		"to spread out load.")

	fs.BoolVar(&s.EnableInflightQuotaHandler, "enable-inflight-quota-handler", s.EnableInflightQuotaHandler, ""+
		"If true, replace the max-in-flight handler with an enhanced one that queues and dispatches with priority and fairness")

	fs.DurationVar(&s.ShutdownDelayDuration, "shutdown-delay-duration", s.ShutdownDelayDuration, ""+
		"Time to delay the termination. During that time the server keeps serving requests normally and /healthz "+
		"returns success, but /readzy immediately returns failure. Graceful termination starts after this delay "+
		"has elapsed. This can be used to allow load balancer to stop sending traffic to this server.")

	utilfeature.DefaultMutableFeatureGate.AddFlag(fs)
}
<commit_msg>Fix typo<commit_after>/*
Copyright 2016 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 options

import (
	"fmt"
	"net"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apiserver/pkg/server"
	utilfeature "k8s.io/apiserver/pkg/util/feature"

	// add the generic feature gates
	"k8s.io/apiserver/pkg/features"

	"github.com/spf13/pflag"
)

// ServerRunOptions contains the options while running a generic api server.
type ServerRunOptions struct {
	AdvertiseAddress net.IP

	CorsAllowedOriginList       []string
	ExternalHost                string
	MaxRequestsInFlight         int
	MaxMutatingRequestsInFlight int
	RequestTimeout              time.Duration
	LivezGracePeriod            time.Duration
	MinRequestTimeout           int
	ShutdownDelayDuration       time.Duration
	// We intentionally did not add a flag for this option. Users of the
	// apiserver library can wire it to a flag.
	JSONPatchMaxCopyBytes int64
	// The limit on the request body size that would be accepted and
	// decoded in a write request. 0 means no limit.
	// We intentionally did not add a flag for this option. Users of the
	// apiserver library can wire it to a flag.
	MaxRequestBodyBytes        int64
	TargetRAMMB                int
	EnableInflightQuotaHandler bool
}

func NewServerRunOptions() *ServerRunOptions {
	defaults := server.NewConfig(serializer.CodecFactory{})
	return &ServerRunOptions{
		MaxRequestsInFlight:         defaults.MaxRequestsInFlight,
		MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
		RequestTimeout:              defaults.RequestTimeout,
		LivezGracePeriod:            defaults.LivezGracePeriod,
		MinRequestTimeout:           defaults.MinRequestTimeout,
		ShutdownDelayDuration:       defaults.ShutdownDelayDuration,
		JSONPatchMaxCopyBytes:       defaults.JSONPatchMaxCopyBytes,
		MaxRequestBodyBytes:         defaults.MaxRequestBodyBytes,
	}
}

// ApplyOptions applies the run options to the method receiver and returns self
func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
	c.CorsAllowedOriginList = s.CorsAllowedOriginList
	c.ExternalAddress = s.ExternalHost
	c.MaxRequestsInFlight = s.MaxRequestsInFlight
	c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
	c.LivezGracePeriod = s.LivezGracePeriod
	c.RequestTimeout = s.RequestTimeout
	c.MinRequestTimeout = s.MinRequestTimeout
	c.ShutdownDelayDuration = s.ShutdownDelayDuration
	c.JSONPatchMaxCopyBytes = s.JSONPatchMaxCopyBytes
	c.MaxRequestBodyBytes = s.MaxRequestBodyBytes
	c.PublicAddress = s.AdvertiseAddress

	return nil
}

// DefaultAdvertiseAddress sets the field AdvertiseAddress if unset. The field will be set based on the SecureServingOptions.
func (s *ServerRunOptions) DefaultAdvertiseAddress(secure *SecureServingOptions) error {
	if secure == nil {
		return nil
	}

	if s.AdvertiseAddress == nil || s.AdvertiseAddress.IsUnspecified() {
		hostIP, err := secure.DefaultExternalAddress()
		if err != nil {
			return fmt.Errorf("Unable to find suitable network address.error='%v'. "+
				"Try to set the AdvertiseAddress directly or provide a valid BindAddress to fix this.", err)
		}
		s.AdvertiseAddress = hostIP
	}

	return nil
}

// Validate checks validation of ServerRunOptions
func (s *ServerRunOptions) Validate() []error {
	errors := []error{}
	if s.TargetRAMMB < 0 {
		errors = append(errors, fmt.Errorf("--target-ram-mb can not be negative value"))
	}

	if s.LivezGracePeriod < 0 {
		errors = append(errors, fmt.Errorf("--livez-grace-period can not be a negative value"))
	}

	if s.EnableInflightQuotaHandler {
		if !utilfeature.DefaultFeatureGate.Enabled(features.RequestManagement) {
			errors = append(errors, fmt.Errorf("--enable-inflight-quota-handler can not be set if feature "+
				"gate RequestManagement is disabled"))
		}
		if s.MaxMutatingRequestsInFlight != 0 {
			errors = append(errors, fmt.Errorf("--max-mutating-requests-inflight=%v "+
				"can not be set if enabled inflight quota handler", s.MaxMutatingRequestsInFlight))
		}
		if s.MaxRequestsInFlight != 0 {
			errors = append(errors, fmt.Errorf("--max-requests-inflight=%v "+
				"can not be set if enabled inflight quota handler", s.MaxRequestsInFlight))
		}
	} else {
		if s.MaxRequestsInFlight < 0 {
			errors = append(errors, fmt.Errorf("--max-requests-inflight can not be negative value"))
		}
		if s.MaxMutatingRequestsInFlight < 0 {
			errors = append(errors, fmt.Errorf("--max-mutating-requests-inflight can not be negative value"))
		}
	}

	if s.RequestTimeout.Nanoseconds() < 0 {
		errors = append(errors, fmt.Errorf("--request-timeout can not be negative value"))
	}

	if s.MinRequestTimeout < 0 {
		errors = append(errors, fmt.Errorf("--min-request-timeout can not be negative value"))
	}

	if s.ShutdownDelayDuration < 0 {
		errors = append(errors, fmt.Errorf("--shutdown-delay-duration can not be negative value"))
	}

	if s.JSONPatchMaxCopyBytes < 0 {
		errors = append(errors, fmt.Errorf("--json-patch-max-copy-bytes can not be negative value"))
	}

	if s.MaxRequestBodyBytes < 0 {
		errors = append(errors, fmt.Errorf("--max-resource-write-bytes can not be negative value"))
	}

	return errors
}

// AddUniversalFlags adds flags for a specific APIServer to the specified FlagSet
func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
	// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
	// arrange these text blocks sensibly. Grrr.

	fs.IPVar(&s.AdvertiseAddress, "advertise-address", s.AdvertiseAddress, ""+
		"The IP address on which to advertise the apiserver to members of the cluster. This "+
		"address must be reachable by the rest of the cluster. If blank, the --bind-address "+
		"will be used. If --bind-address is unspecified, the host's default interface will "+
		"be used.")

	fs.StringSliceVar(&s.CorsAllowedOriginList, "cors-allowed-origins", s.CorsAllowedOriginList, ""+
		"List of allowed origins for CORS, comma separated.  An allowed origin can be a regular "+
		"expression to support subdomain matching. If this list is empty CORS will not be enabled.")

	fs.IntVar(&s.TargetRAMMB, "target-ram-mb", s.TargetRAMMB,
		"Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")

	fs.StringVar(&s.ExternalHost, "external-hostname", s.ExternalHost,
		"The hostname to use when generating externalized URLs for this master (e.g. Swagger API Docs).")

	deprecatedMasterServiceNamespace := metav1.NamespaceDefault
	fs.StringVar(&deprecatedMasterServiceNamespace, "master-service-namespace", deprecatedMasterServiceNamespace, ""+
		"DEPRECATED: the namespace from which the kubernetes master services should be injected into pods.")

	fs.IntVar(&s.MaxRequestsInFlight, "max-requests-inflight", s.MaxRequestsInFlight, ""+
		"The maximum number of non-mutating requests in flight at a given time. When the server exceeds this, "+
		"it rejects requests. Zero for no limit.")

	fs.IntVar(&s.MaxMutatingRequestsInFlight, "max-mutating-requests-inflight", s.MaxMutatingRequestsInFlight, ""+
		"The maximum number of mutating requests in flight at a given time. When the server exceeds this, "+
		"it rejects requests. Zero for no limit.")

	fs.DurationVar(&s.RequestTimeout, "request-timeout", s.RequestTimeout, ""+
		"An optional field indicating the duration a handler must keep a request open before timing "+
		"it out. This is the default request timeout for requests but may be overridden by flags such as "+
		"--min-request-timeout for specific types of requests.")

	fs.DurationVar(&s.LivezGracePeriod, "livez-grace-period", s.LivezGracePeriod, ""+
		"This option represents the maximum amount of time it should take for apiserver to complete its startup sequence "+
		"and become live. From apiserver's start time to when this amount of time has elapsed, /livez will assume "+
		"that unfinished post-start hooks will complete successfully and therefore return true.")

	fs.IntVar(&s.MinRequestTimeout, "min-request-timeout", s.MinRequestTimeout, ""+
		"An optional field indicating the minimum number of seconds a handler must keep "+
		"a request open before timing it out. Currently only honored by the watch request "+
		"handler, which picks a randomized value above this number as the connection timeout, "+
		"to spread out load.")

	fs.BoolVar(&s.EnableInflightQuotaHandler, "enable-inflight-quota-handler", s.EnableInflightQuotaHandler, ""+
		"If true, replace the max-in-flight handler with an enhanced one that queues and dispatches with priority and fairness")

	fs.DurationVar(&s.ShutdownDelayDuration, "shutdown-delay-duration", s.ShutdownDelayDuration, ""+
		"Time to delay the termination. During that time the server keeps serving requests normally and /healthz "+
		"returns success, but /readyz immediately returns failure. Graceful termination starts after this delay "+
		"has elapsed. This can be used to allow load balancer to stop sending traffic to this server.")

	utilfeature.DefaultMutableFeatureGate.AddFlag(fs)
}
<|endoftext|>


<commit_before>package docker

import (
	"os"
	"time"

	dockertools "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	"github.com/spf13/pflag"
)

// Helper contains all the valid config options for connecting to Docker from
// a command line.
type Helper struct {
}

// NewHelper creates a Flags object with the default values set.  Use this
// to use consistent Docker client loading behavior from different contexts.
func NewHelper() *Helper {
	return &Helper{}
}

// InstallFlags installs the Docker flag helper into a FlagSet with the default
// options and default values from the Helper object.
func (_ *Helper) InstallFlags(flags *pflag.FlagSet) {
}

// GetClient returns a valid Docker client, the address of the client, or an error
// if the client couldn't be created.
func (_ *Helper) GetClient() (client *docker.Client, endpoint string, err error) {
	client, err = docker.NewClientFromEnv()
	if len(os.Getenv("DOCKER_HOST")) > 0 {
		endpoint = os.Getenv("DOCKER_HOST")
	} else {
		endpoint = "unix:///var/run/docker.sock"
	}
	return
}

// GetKubeClient returns the Kubernetes Docker client.
func (_ *Helper) GetKubeClient(requestTimeout, imagePullProgressDeadline time.Duration) (*KubeDocker, string, error) {
	var endpoint string
	if len(os.Getenv("DOCKER_HOST")) > 0 {
		endpoint = os.Getenv("DOCKER_HOST")
	} else {
		endpoint = "unix:///var/run/docker.sock"
	}
	client := dockertools.ConnectToDockerOrDie(endpoint, requestTimeout, imagePullProgressDeadline)
	originClient := &KubeDocker{client}
	return originClient, endpoint, nil
}

// GetClientOrExit returns a valid Docker client and the address of the client,
// or prints an error and exits.
func (h *Helper) GetClientOrExit() (*docker.Client, string) {
	client, addr, err := h.GetClient()
	if err != nil {
		glog.Fatalf("ERROR: Couldn't connect to Docker at %s.\n%v\n.", addr, err)
	}
	return client, addr
}

// KubeDocker provides a wrapper to Kubernetes Docker interface
// This wrapper is compatible with OpenShift Docker interface.
type KubeDocker struct {
	dockertools.Interface
}

// Ping implements the DockerInterface Ping method.
func (c *KubeDocker) Ping() error {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	return client.Ping()
}
<commit_msg>NEEDS REVIEW: boring: docker client update<commit_after>package docker

import (
	"os"
	"time"

	dockertools "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	"github.com/spf13/pflag"
)

// Helper contains all the valid config options for connecting to Docker from
// a command line.
type Helper struct {
}

// NewHelper creates a Flags object with the default values set.  Use this
// to use consistent Docker client loading behavior from different contexts.
func NewHelper() *Helper {
	return &Helper{}
}

// InstallFlags installs the Docker flag helper into a FlagSet with the default
// options and default values from the Helper object.
func (_ *Helper) InstallFlags(flags *pflag.FlagSet) {
}

// GetClient returns a valid Docker client, the address of the client, or an error
// if the client couldn't be created.
func (_ *Helper) GetClient() (client *docker.Client, endpoint string, err error) {
	client, err = docker.NewClientFromEnv()
	if len(os.Getenv("DOCKER_HOST")) > 0 {
		endpoint = os.Getenv("DOCKER_HOST")
	} else {
		endpoint = "unix:///var/run/docker.sock"
	}
	return
}

// GetKubeClient returns the Kubernetes Docker client.
func (_ *Helper) GetKubeClient(requestTimeout, imagePullProgressDeadline time.Duration) (*KubeDocker, string, error) {
	var endpoint string
	if len(os.Getenv("DOCKER_HOST")) > 0 {
		endpoint = os.Getenv("DOCKER_HOST")
	} else {
		endpoint = "unix:///var/run/docker.sock"
	}
	client := dockertools.ConnectToDockerOrDie(endpoint, requestTimeout, imagePullProgressDeadline, false, false)
	originClient := &KubeDocker{client}
	return originClient, endpoint, nil
}

// GetClientOrExit returns a valid Docker client and the address of the client,
// or prints an error and exits.
func (h *Helper) GetClientOrExit() (*docker.Client, string) {
	client, addr, err := h.GetClient()
	if err != nil {
		glog.Fatalf("ERROR: Couldn't connect to Docker at %s.\n%v\n.", addr, err)
	}
	return client, addr
}

// KubeDocker provides a wrapper to Kubernetes Docker interface
// This wrapper is compatible with OpenShift Docker interface.
type KubeDocker struct {
	dockertools.Interface
}

// Ping implements the DockerInterface Ping method.
func (c *KubeDocker) Ping() error {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	return client.Ping()
}
<|endoftext|>