<commit_before>// Package pinata is a utility to beat data out of interface{}, []interface{}
// and map[string]interface{}.
package pinata

import (
	"bytes"
	"fmt"
	"strings"
)

// Stick offers methods for extracting data from a Pinata.
type Stick interface {
	Error() error
	ClearError()
	PathString(Pinata, ...string) string
	String(Pinata) string
	IndexString(Pinata, int) string
	PathPinata(Pinata, ...string) Pinata
	IndexPinata(Pinata, int) Pinata
}

type ErrorContext struct {
	method      string
	methodInput []interface{}
	next        *ErrorContext
}

// Method returns the name of the method that caused the error.
func (ec ErrorContext) Method() string {
	return ec.method
}

// MethodInput returns the input parameters of the method that caused the error.
func (ec ErrorContext) MethodInput() []interface{} {
	return ec.methodInput
}

func (ec ErrorContext) Next() *ErrorContext {
	return ec.next
}

type Pinata struct {
	context  *ErrorContext
	contents contents
}

func (p Pinata) Value() interface{} {
	return p.contents.Value()
}

func (p Pinata) Map() (map[string]interface{}, bool) {
	return p.contents.Map()
}

func (p Pinata) Slice() ([]interface{}, bool) {
	return p.contents.Slice()
}

type contents interface {
	Value() interface{}
	Map() (map[string]interface{}, bool)
	Slice() ([]interface{}, bool)
}

type otherPinata struct {
	value interface{}
}

func (p otherPinata) Value() interface{} {
	return p.value
}

func (p otherPinata) Map() (map[string]interface{}, bool) {
	return nil, false
}

func (p otherPinata) Slice() ([]interface{}, bool) {
	return nil, false
}

var _ = contents(mapPinata{})

type mapPinata struct {
	otherPinata
	value map[string]interface{}
}

func (p mapPinata) Map() (map[string]interface{}, bool) {
	return p.value, true
}

type slicePinata struct {
	otherPinata
	value []interface{}
}

func (p slicePinata) Slice() ([]interface{}, bool) {
	return p.value, true
}

// New is a starting point for a pinata celebration.
func New(contents interface{}) (Stick, Pinata) {
	return NewStick(), NewPinata(contents)
}

func NewStick() Stick {
	return &stick{}
}

// New creates a new Stick. Instances returned are not thread safe.
func NewPinata(contents interface{}) Pinata {
	return newPinataWithContext(contents, nil)
}

func newPinataWithContext(contents interface{}, context *ErrorContext) Pinata {
	switch t := contents.(type) {
	case map[string]interface{}:
		return Pinata{contents: &mapPinata{value: t}, context: context}
	case []interface{}:
		return Pinata{contents: &slicePinata{value: t}, context: context}
	default:
		return Pinata{contents: &otherPinata{value: t}, context: context}
	}
}

var _ = error(PinataError{})

// ErrorReason describes the reason for returning a PinataError.
type ErrorReason string

const (
	// ErrorReasonIncompatibleType indicates the contents of the Pinata is not compatible with the invoked method.
	ErrorReasonIncompatibleType ErrorReason = "incompatible type"
	// ErrorReasonNotFound indicates the input has not been found in the Pinata.
	ErrorReasonNotFound = "not found"
	// ErrorReasonInvalidInput indicates the input is not in the expected range or format.
	ErrorReasonInvalidInput = "invalid input"
)

// PinataError is set on the Pinata if something goes wrong.
type PinataError struct {
	reason  ErrorReason
	context *ErrorContext
	advice  string
}

// Reason indicates why the error occurred.
func (p PinataError) Reason() ErrorReason {
	return p.reason
}

// Context returns more information about the circumstances of the error.
func (p PinataError) Context() *ErrorContext {
	return p.context
}

// Advice contains a human readable hint detailing how to remedy this error.
func (p PinataError) Advice() string {
	return p.advice
}

func (p PinataError) Error() string {
	var summaries []string
	current := p.context
	for current != nil {
		var methodInput = current.MethodInput()
		var summary string
		if len(methodInput) > 0 {
			var buf bytes.Buffer
			_, _ = buf.WriteString(current.Method())
			_ = buf.WriteByte('(')
			for i := range methodInput {
				_, _ = buf.WriteString("%#v")
				if i < len(methodInput)-1 {
					_, _ = buf.WriteString(", ")
				}
			}
			_ = buf.WriteByte(')')
			summary = fmt.Sprintf(buf.String(), methodInput...)
			summaries = append(summaries, summary)
		}
		current = current.next
	}
	return fmt.Sprintf("pinata: %s (%s) - %v", p.Reason(), p.Advice(), summaries)
}

type stick struct {
	err error
}

func (s *stick) ClearError() {
	s.err = nil
}

func (s *stick) Error() error {
	return s.err
}

// this method assumes s.err != nil
func (s *stick) stringUnsupported(errCtx *ErrorContext, advice string) string {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      "String",
			methodInput: nil,
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: advice,
	}
	return ""
}

// this method assumes s.err != nil
func (s *stick) indexUnsupported(errCtx *ErrorContext, method string, index int) {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a slice pinata",
	}
}

// this method assumes s.err != nil
func (s *stick) setIndexOutOfRange(errCtx *ErrorContext, method string, index int, contents []interface{}) bool {
	if index < 0 || index >= len(contents) {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: []interface{}{index},
				next:        errCtx,
			},
			reason: ErrorReasonInvalidInput,
			advice: fmt.Sprintf("specify an index from 0 to %d", len(contents)-1),
		}
		return true
	}
	return false
}

// this method assumes s.err != nil
func (s *stick) pathUnsupported(errCtx *ErrorContext, method string, path []string) {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a map pinata",
	}
}

func (s *stick) String(p Pinata) string {
	if s.err != nil {
		return ""
	}
	if _, ok := p.Map(); ok {
		return s.stringUnsupported(p.context, "this is a map")
	}
	if _, ok := p.Slice(); ok {
		return s.stringUnsupported(p.context, "this is a slice")
	}
	if v, ok := p.Value().(string); ok {
		return v
	}
	return s.stringUnsupported(p.context, "this is not a string")
}

// this method assumes s.err != nil
func (s *stick) indexPinata(p Pinata, method string, index int) Pinata {
	if slice, ok := p.Slice(); ok {
		if s.setIndexOutOfRange(p.context, method, index, slice) {
			return Pinata{}
		}
		return newPinataWithContext(slice[index], &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        p.context,
		})
	}
	s.indexUnsupported(p.context, method, index)
	return Pinata{}
}

func (s *stick) IndexPinata(p Pinata, index int) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.indexPinata(p, "IndexPinata", index)
}

func (s *stick) IndexString(p Pinata, index int) string {
	if s.err != nil {
		return ""
	}
	const method = "IndexString"
	pinata := s.indexPinata(p, method, index)
	if s.err != nil {
		return ""
	}
	str := s.String(pinata)
	if s.err != nil {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: []interface{}{index},
				next:        p.context,
			},
			reason: ErrorReasonIncompatibleType,
			advice: "not a string, try another type",
		}
		return ""
	}
	return str
}

// this method assumes s.err != nil
func (s *stick) pathPinata(p Pinata, method string, path ...string) Pinata {
	contents, ok := p.Map()

	if !ok {
		s.pathUnsupported(p.context, method, path)
		return Pinata{}
	}

	if len(path) == 0 {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: toInterfaceSlice(path),
				next:        p.context,
			},
			reason: ErrorReasonInvalidInput,
			advice: "specify a path",
		}
		return Pinata{}
	}

	for i := 0; i < len(path)-1; i++ {
		current := path[i]
		if v, ok := contents[current]; ok {
			if v, ok := v.(map[string]interface{}); ok {
				contents = v
			} else {
				s.err = &PinataError{
					context: &ErrorContext{
						method:      method,
						methodInput: toInterfaceSlice(path),
						next:        p.context,
					},
					reason: ErrorReasonIncompatibleType,
					advice: fmt.Sprintf(`"%s" does not hold a pinata`, strings.Join(path[:i+1], `", "`)),
				}
				return Pinata{}
			}
		} else {
			s.err = &PinataError{
				context: &ErrorContext{
					method:      method,
					methodInput: toInterfaceSlice(path),
					next:        p.context,
				},
				reason: ErrorReasonNotFound,
				advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path[:i+1], `", "`)),
			}
			return Pinata{}
		}
	}

	if v, ok := contents[path[len(path)-1]]; ok {
		return newPinataWithContext(v, &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		})
	}

	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		},
		reason: ErrorReasonNotFound,
		advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path, `", "`)),
	}
	return Pinata{}
}

func (s *stick) PathPinata(p Pinata, path ...string) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.pathPinata(p, "PathPinata", path...)
}

func (s *stick) PathString(p Pinata, path ...string) string {
	if s.err != nil {
		return ""
	}
	const method = "PathString"
	pinata := s.pathPinata(p, method, path...)
	if s.err != nil {
		return ""
	}
	str := s.String(pinata)
	if s.err != nil {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: toInterfaceSlice(path),
				next:        p.context,
			},
			reason: ErrorReasonIncompatibleType,
			advice: "not a string, try another type",
		}
	}
	return str
}

func toInterfaceSlice(c []string) []interface{} {
	ifaces := make([]interface{}, len(c))
	for i := range c {
		ifaces[i] = c[i]
	}
	return ifaces
}
<commit_msg>display stack in a friendlier format<commit_after>// Package pinata is a utility to beat data out of interface{}, []interface{}
// and map[string]interface{}.
package pinata

import (
	"bytes"
	"fmt"
	"strings"
)

// Stick offers methods for extracting data from a Pinata.
type Stick interface {
	Error() error
	ClearError()
	PathString(Pinata, ...string) string
	String(Pinata) string
	IndexString(Pinata, int) string
	PathPinata(Pinata, ...string) Pinata
	IndexPinata(Pinata, int) Pinata
}

type ErrorContext struct {
	method      string
	methodInput []interface{}
	next        *ErrorContext
}

// Method returns the name of the method that caused the error.
func (ec ErrorContext) Method() string {
	return ec.method
}

// MethodInput returns the input parameters of the method that caused the error.
func (ec ErrorContext) MethodInput() []interface{} {
	return ec.methodInput
}

func (ec ErrorContext) Next() *ErrorContext {
	return ec.next
}

type Pinata struct {
	context  *ErrorContext
	contents contents
}

func (p Pinata) Value() interface{} {
	return p.contents.Value()
}

func (p Pinata) Map() (map[string]interface{}, bool) {
	return p.contents.Map()
}

func (p Pinata) Slice() ([]interface{}, bool) {
	return p.contents.Slice()
}

type contents interface {
	Value() interface{}
	Map() (map[string]interface{}, bool)
	Slice() ([]interface{}, bool)
}

type otherPinata struct {
	value interface{}
}

func (p otherPinata) Value() interface{} {
	return p.value
}

func (p otherPinata) Map() (map[string]interface{}, bool) {
	return nil, false
}

func (p otherPinata) Slice() ([]interface{}, bool) {
	return nil, false
}

var _ = contents(mapPinata{})

type mapPinata struct {
	otherPinata
	value map[string]interface{}
}

func (p mapPinata) Map() (map[string]interface{}, bool) {
	return p.value, true
}

type slicePinata struct {
	otherPinata
	value []interface{}
}

func (p slicePinata) Slice() ([]interface{}, bool) {
	return p.value, true
}

// New is a starting point for a pinata celebration.
func New(contents interface{}) (Stick, Pinata) {
	return NewStick(), NewPinata(contents)
}

func NewStick() Stick {
	return &stick{}
}

// New creates a new Stick. Instances returned are not thread safe.
func NewPinata(contents interface{}) Pinata {
	return newPinataWithContext(contents, nil)
}

func newPinataWithContext(contents interface{}, context *ErrorContext) Pinata {
	switch t := contents.(type) {
	case map[string]interface{}:
		return Pinata{contents: &mapPinata{value: t}, context: context}
	case []interface{}:
		return Pinata{contents: &slicePinata{value: t}, context: context}
	default:
		return Pinata{contents: &otherPinata{value: t}, context: context}
	}
}

var _ = error(PinataError{})

// ErrorReason describes the reason for returning a PinataError.
type ErrorReason string

const (
	// ErrorReasonIncompatibleType indicates the contents of the Pinata is not compatible with the invoked method.
	ErrorReasonIncompatibleType ErrorReason = "incompatible type"
	// ErrorReasonNotFound indicates the input has not been found in the Pinata.
	ErrorReasonNotFound = "not found"
	// ErrorReasonInvalidInput indicates the input is not in the expected range or format.
	ErrorReasonInvalidInput = "invalid input"
)

// PinataError is set on the Pinata if something goes wrong.
type PinataError struct {
	reason  ErrorReason
	context *ErrorContext
	advice  string
}

// Reason indicates why the error occurred.
func (p PinataError) Reason() ErrorReason {
	return p.reason
}

// Context returns more information about the circumstances of the error.
func (p PinataError) Context() *ErrorContext {
	return p.context
}

// Advice contains a human readable hint detailing how to remedy this error.
func (p PinataError) Advice() string {
	return p.advice
}

func (p PinataError) Error() string {
	var summaries []string
	current := p.context
	for current != nil {
		var methodInput = current.MethodInput()
		var summary string
		if len(methodInput) > 0 {
			var buf bytes.Buffer
			_, _ = buf.WriteString(current.Method())
			_ = buf.WriteByte('(')
			for i := range methodInput {
				_, _ = buf.WriteString("%#v")
				if i < len(methodInput)-1 {
					_, _ = buf.WriteString(", ")
				}
			}
			_ = buf.WriteByte(')')
			summary = fmt.Sprintf(buf.String(), methodInput...)
			summaries = append(summaries, summary)
		}
		current = current.next
	}
	return fmt.Sprintf("pinata: %s (%s): \n\t%v", p.Reason(), p.Advice(), strings.Join(summaries, " <= "))
}

type stick struct {
	err error
}

func (s *stick) ClearError() {
	s.err = nil
}

func (s *stick) Error() error {
	return s.err
}

// this method assumes s.err != nil
func (s *stick) stringUnsupported(errCtx *ErrorContext, advice string) string {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      "String",
			methodInput: nil,
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: advice,
	}
	return ""
}

// this method assumes s.err != nil
func (s *stick) indexUnsupported(errCtx *ErrorContext, method string, index int) {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a slice pinata",
	}
}

// this method assumes s.err != nil
func (s *stick) setIndexOutOfRange(errCtx *ErrorContext, method string, index int, contents []interface{}) bool {
	if index < 0 || index >= len(contents) {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: []interface{}{index},
				next:        errCtx,
			},
			reason: ErrorReasonInvalidInput,
			advice: fmt.Sprintf("specify an index from 0 to %d", len(contents)-1),
		}
		return true
	}
	return false
}

// this method assumes s.err != nil
func (s *stick) pathUnsupported(errCtx *ErrorContext, method string, path []string) {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a map pinata",
	}
}

func (s *stick) String(p Pinata) string {
	if s.err != nil {
		return ""
	}
	if _, ok := p.Map(); ok {
		return s.stringUnsupported(p.context, "this is a map")
	}
	if _, ok := p.Slice(); ok {
		return s.stringUnsupported(p.context, "this is a slice")
	}
	if v, ok := p.Value().(string); ok {
		return v
	}
	return s.stringUnsupported(p.context, "this is not a string")
}

// this method assumes s.err != nil
func (s *stick) indexPinata(p Pinata, method string, index int) Pinata {
	if slice, ok := p.Slice(); ok {
		if s.setIndexOutOfRange(p.context, method, index, slice) {
			return Pinata{}
		}
		return newPinataWithContext(slice[index], &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        p.context,
		})
	}
	s.indexUnsupported(p.context, method, index)
	return Pinata{}
}

func (s *stick) IndexPinata(p Pinata, index int) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.indexPinata(p, "IndexPinata", index)
}

func (s *stick) IndexString(p Pinata, index int) string {
	if s.err != nil {
		return ""
	}
	const method = "IndexString"
	pinata := s.indexPinata(p, method, index)
	if s.err != nil {
		return ""
	}
	str := s.String(pinata)
	if s.err != nil {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: []interface{}{index},
				next:        p.context,
			},
			reason: ErrorReasonIncompatibleType,
			advice: "not a string, try another type",
		}
		return ""
	}
	return str
}

// this method assumes s.err != nil
func (s *stick) pathPinata(p Pinata, method string, path ...string) Pinata {
	contents, ok := p.Map()

	if !ok {
		s.pathUnsupported(p.context, method, path)
		return Pinata{}
	}

	if len(path) == 0 {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: toInterfaceSlice(path),
				next:        p.context,
			},
			reason: ErrorReasonInvalidInput,
			advice: "specify a path",
		}
		return Pinata{}
	}

	for i := 0; i < len(path)-1; i++ {
		current := path[i]
		if v, ok := contents[current]; ok {
			if v, ok := v.(map[string]interface{}); ok {
				contents = v
			} else {
				s.err = &PinataError{
					context: &ErrorContext{
						method:      method,
						methodInput: toInterfaceSlice(path),
						next:        p.context,
					},
					reason: ErrorReasonIncompatibleType,
					advice: fmt.Sprintf(`"%s" does not hold a pinata`, strings.Join(path[:i+1], `", "`)),
				}
				return Pinata{}
			}
		} else {
			s.err = &PinataError{
				context: &ErrorContext{
					method:      method,
					methodInput: toInterfaceSlice(path),
					next:        p.context,
				},
				reason: ErrorReasonNotFound,
				advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path[:i+1], `", "`)),
			}
			return Pinata{}
		}
	}

	if v, ok := contents[path[len(path)-1]]; ok {
		return newPinataWithContext(v, &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		})
	}

	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		},
		reason: ErrorReasonNotFound,
		advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path, `", "`)),
	}
	return Pinata{}
}

func (s *stick) PathPinata(p Pinata, path ...string) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.pathPinata(p, "PathPinata", path...)
}

func (s *stick) PathString(p Pinata, path ...string) string {
	if s.err != nil {
		return ""
	}
	const method = "PathString"
	pinata := s.pathPinata(p, method, path...)
	if s.err != nil {
		return ""
	}
	str := s.String(pinata)
	if s.err != nil {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: toInterfaceSlice(path),
				next:        p.context,
			},
			reason: ErrorReasonIncompatibleType,
			advice: "not a string, try another type",
		}
	}
	return str
}

func toInterfaceSlice(c []string) []interface{} {
	ifaces := make([]interface{}, len(c))
	for i := range c {
		ifaces[i] = c[i]
	}
	return ifaces
}
<|endoftext|>


<commit_before>package uploads

import (
	"sync"

	"github.com/materials-commons/gohandy/file"
	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/willf/bitset"
	"path/filepath"
)

// blockTracker holds all the state of blocks for different upload requests.
// If a block has been successfully written then it is marked, otherwise
// the block is clear and no data has been written for it.
type blockTracker struct {
	mutex       sync.RWMutex
	requestPath requestPath
	fops        file.Operations
	reqBlocks   map[string]*bitset.BitSet
}

// newBlockTracker creates a new blockTracker instance.
func newBlockTracker() *blockTracker {
	return &blockTracker{
		requestPath: &mcdirRequestPath{},
		fops:        file.OS,
		reqBlocks:   make(map[string]*bitset.BitSet),
	}
}

// setBlock marks a block as having the data written for it.
func (t *blockTracker) setBlock(id string, block int) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	bset, found := t.reqBlocks[id]
	if !found {
		// need to load this items blocks.
		t.loadBlocks(id)
		bset = t.reqBlocks[id]
	}
	bset.Set(uint(block))
}

func (t *blockTracker) loadBlocks(id string) {
	path := BlocksFile(t.requestPath, id)
	f, err := t.fops.Open(path)
	if err != nil {
		app.Log.Panicf("Can't load block file for request %s (path %s): %s", id, path, err)
	}
	defer f.Close()
	var bset bitset.BitSet
	bset.ReadFrom(f)
	t.reqBlocks[id] = &bset
}

func (t *blockTracker) persist(id string) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	bset := t.reqBlocks[id]
	t.writeBlocks(bset, id)
}

func (t *blockTracker) persistAll() {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	for id, bset := range t.reqBlocks {
		t.writeBlocks(bset, id)
	}
}

func (t *blockTracker) writeBlocks(bset *bitset.BitSet, id string) {
	path := BlocksFile(t.requestPath, id)
	f, err := t.fops.Create(path)
	if err != nil {
		app.Log.Panicf("Can't write block file for request %s (path %s): %s", id, path, err)
	}
	defer f.Close()
	bset.WriteTo(f)
}

// clearBlock unmarks a block.
func (t *blockTracker) clearBlock(id string, block int) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	bset := t.reqBlocks[id]
	bset.SetTo(uint(block), false)
}

// done returns true if all blocks have been marked for an id.
func (t *blockTracker) done(id string) bool {
	defer t.mutex.Unlock()
	t.mutex.RLock()
	bset := t.reqBlocks[id]
	return bset.All()
}

// clear removes an id from the block tracker.
func (t *blockTracker) clear(id string) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	delete(t.reqBlocks, id)
}

func BlocksFile(rpath requestPath, id string) (path string) {
	return filepath.Join(rpath.dirFromID(id), "blocks")
}
<commit_msg>Add comments. Run goimports.<commit_after>package uploads

import (
	"sync"

	"path/filepath"

	"github.com/materials-commons/gohandy/file"
	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/willf/bitset"
)

// blockTracker holds all the state of blocks for different upload requests.
// If a block has been successfully written then it is marked, otherwise
// the block is clear and no data has been written for it.
type blockTracker struct {
	mutex       sync.RWMutex
	requestPath requestPath
	fops        file.Operations
	reqBlocks   map[string]*bitset.BitSet
}

// newBlockTracker creates a new blockTracker instance.
func newBlockTracker() *blockTracker {
	return &blockTracker{
		requestPath: &mcdirRequestPath{},
		fops:        file.OS,
		reqBlocks:   make(map[string]*bitset.BitSet),
	}
}

// setBlock marks a block as having the data written for it.
func (t *blockTracker) setBlock(id string, block int) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	bset, found := t.reqBlocks[id]
	if !found {
		// need to load this items blocks.
		t.loadBlocks(id)
		bset = t.reqBlocks[id]
	}
	bset.Set(uint(block))
}

// loadBlocks will load the blocks bitset for an id. It panics if it cannot
// read the blocks file.
func (t *blockTracker) loadBlocks(id string) {
	path := BlocksFile(t.requestPath, id)
	f, err := t.fops.Open(path)
	if err != nil {
		app.Log.Panicf("Can't load block file for request %s (path %s): %s", id, path, err)
	}
	defer f.Close()
	var bset bitset.BitSet
	bset.ReadFrom(f)
	t.reqBlocks[id] = &bset
}

// persist writes the blocks bitset to the blocks file. It panics if it cannot
// write the blocks file.
func (t *blockTracker) persist(id string) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	bset := t.reqBlocks[id]
	t.writeBlocks(bset, id)
}

// persistAll writes all the blocks bitsets to their respective blocks file
// for each id that is being tracked by the blocks tracker. It panics if
// any of these fails to persist.
func (t *blockTracker) persistAll() {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	for id, bset := range t.reqBlocks {
		t.writeBlocks(bset, id)
	}
}

// writeBlocks performs the operation of writing the blocks file. It doesn't
// take out any locks and should never be called directly.
func (t *blockTracker) writeBlocks(bset *bitset.BitSet, id string) {
	path := BlocksFile(t.requestPath, id)
	f, err := t.fops.Create(path)
	if err != nil {
		app.Log.Panicf("Can't write block file for request %s (path %s): %s", id, path, err)
	}
	defer f.Close()
	bset.WriteTo(f)
}

// clearBlock unmarks a block.
func (t *blockTracker) clearBlock(id string, block int) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	bset := t.reqBlocks[id]
	bset.SetTo(uint(block), false)
}

// done returns true if all blocks have been marked for an id.
func (t *blockTracker) done(id string) bool {
	defer t.mutex.Unlock()
	t.mutex.RLock()
	bset := t.reqBlocks[id]
	return bset.All()
}

// clear removes an id from the block tracker.
func (t *blockTracker) clear(id string) {
	defer t.mutex.Unlock()
	t.mutex.Lock()
	delete(t.reqBlocks, id)
}

// BlocksFile returns the path to the blocks file for a given id.
func BlocksFile(rpath requestPath, id string) (path string) {
	return filepath.Join(rpath.dirFromID(id), "blocks")
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "strconv"
    "strings"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/ecs"
)

type Plugin struct {
    Key                     string
    Secret                  string
    Region                  string
    Family                  string
    TaskRoleArn             string
    Service                 string
    ContainerName           string
    DockerImage             string
    Tag                     string
    Cluster                 string
    DeploymentConfiguration string
    LogDriver               string
    LogOptions              []string
    PortMappings            []string
    DockerLabels            []string
    Environment             []string
    DesiredCount            int64
    CPU                     int64
    Memory                  int64
    MemoryReservation       int64
    YamlVerified            bool
}

func (p *Plugin) Exec() error {
    fmt.Println("Drone AWS ECS Plugin built")
    fmt.Println("pirates")
    awsConfig := aws.Config{}

    if len(p.Key) != 0 && len(p.Secret) != 0 {
        awsConfig.Credentials = credentials.NewStaticCredentials(p.Key, p.Secret, "")
    }
    awsConfig.Region = aws.String(p.Region)
    svc := ecs.New(session.New(&awsConfig))

    Image := p.DockerImage + ":" + p.Tag
    if len(p.ContainerName) == 0 {
        p.ContainerName = p.Family + "-container"
    }

    definition := ecs.ContainerDefinition{
        Command: []*string{},

        DnsSearchDomains:      []*string{},
        DnsServers:            []*string{},
        DockerLabels:          map[string]*string{},
        DockerSecurityOptions: []*string{},
        EntryPoint:            []*string{},
        Environment:           []*ecs.KeyValuePair{},
        Essential:             aws.Bool(true),
        ExtraHosts:            []*ecs.HostEntry{},

        Image:        aws.String(Image),
        Links:        []*string{},
        Memory:       aws.Int64(p.Memory),
        MountPoints:  []*ecs.MountPoint{},
        Name:         aws.String(p.ContainerName),
        PortMappings: []*ecs.PortMapping{},

        Ulimits: []*ecs.Ulimit{},
        //User: aws.String("String"),
        VolumesFrom: []*ecs.VolumeFrom{},
        //WorkingDirectory: aws.String("String"),
    }

    if p.CPU != 0 {
        definition.Cpu = aws.Int64(p.CPU)
    }

    if p.Memory == 0 && p.MemoryReservation == 0 {
        definition.MemoryReservation = aws.Int64(128)
    } else {
        if p.Memory != 0 {
            definition.Memory = aws.Int64(p.Memory)
        }
        if p.MemoryReservation != 0 {
            definition.MemoryReservation = aws.Int64(p.MemoryReservation)
        }
    }

    // Port mappings
    for _, portMapping := range p.PortMappings {
        cleanedPortMapping := strings.Trim(portMapping, " ")
        parts := strings.SplitN(cleanedPortMapping, " ", 2)
        hostPort, hostPortErr := strconv.ParseInt(parts[0], 10, 64)
        if hostPortErr != nil {
            fmt.Println(hostPortErr.Error())
            return hostPortErr
        }
        containerPort, containerPortError := strconv.ParseInt(parts[1], 10, 64)
        if containerPortError != nil {
            fmt.Println(containerPortError.Error())
            return containerPortError
        }

        pair := ecs.PortMapping{
            ContainerPort: aws.Int64(containerPort),
            HostPort:      aws.Int64(hostPort),
            Protocol:      aws.String("TransportProtocol"),
        }

        definition.PortMappings = append(definition.PortMappings, &pair)
    }

    // Environment variables
    for _, envVar := range p.Environment {
        parts := strings.SplitN(envVar, "=", 2)
        pair := ecs.KeyValuePair{
            Name:  aws.String(strings.Trim(parts[0], " ")),
            Value: aws.String(strings.Trim(parts[1], " ")),
        }
        definition.Environment = append(definition.Environment, &pair)
    }

    // DockerLabels
    for _, label := range p.DockerLabels {
        parts := strings.SplitN(label, "=", 2)
        definition.DockerLabels[strings.Trim(parts[0], " ")] = aws.String(strings.Trim(parts[1], " "))
    }

    // LogOptions
    if len(p.LogDriver) > 0 {
        definition.LogConfiguration = new(ecs.LogConfiguration)
        definition.LogConfiguration.LogDriver = &p.LogDriver
        if len(p.LogOptions) > 0 {
            definition.LogConfiguration.Options = make(map[string]*string)
            for _, logOption := range p.LogOptions {
                parts := strings.SplitN(logOption, "=", 2)
                logOptionKey := strings.Trim(parts[0], " ")
                logOptionValue := aws.String(strings.Trim(parts[1], " "))
                definition.LogConfiguration.Options[logOptionKey] = logOptionValue
            }
        }
    }

    params := &ecs.RegisterTaskDefinitionInput{
        ContainerDefinitions: []*ecs.ContainerDefinition{
            &definition,
        },
        Family:      aws.String(p.Family),
        Volumes:     []*ecs.Volume{},
        TaskRoleArn: aws.String(p.TaskRoleArn),
    }
    resp, err := svc.RegisterTaskDefinition(params)

    if err != nil {
        fmt.Println(err.Error())
        return err
    }

    val := *(resp.TaskDefinition.TaskDefinitionArn)
    sparams := &ecs.UpdateServiceInput{
        Cluster:        aws.String(p.Cluster),
        Service:        aws.String(p.Service),
        TaskDefinition: aws.String(val),
    }

    if p.DesiredCount != 0 {
        sparams.DesiredCount = aws.Int64(p.DesiredCount)
    }

    // DeploymentConfiguration
    fmt.Println("starting DeploymentConfiguration")
    cleanedDeploymentConfiguration := strings.Trim(p.DeploymentConfiguration, " ")
    parts := strings.SplitN(cleanedDeploymentConfiguration, " ", 2)
    if len(parts) > 1 {
        minimumHealthyPercent, minimumHealthyPercentError := strconv.ParseInt(parts[0], 10, 64)
        if minimumHealthyPercentError != nil {
            fmt.Println(minimumHealthyPercentError.Error())
            return minimumHealthyPercentError
        }
        maximumPercent, maximumPercentErr := strconv.ParseInt(parts[1], 10, 64)
        if maximumPercentErr != nil {
            fmt.Println(maximumPercentErr.Error())
            return maximumPercentErr
        }

        sparams.DeploymentConfiguration = &ecs.DeploymentConfiguration{
            MaximumPercent:        aws.Int64(maximumPercent),
            MinimumHealthyPercent: aws.Int64(minimumHealthyPercent),
        }
    }

    sresp, serr := svc.UpdateService(sparams)

    if serr != nil {
        fmt.Println(serr.Error())
        return serr
    }

    fmt.Println(sresp)

    fmt.Println(resp)
    return nil

}
<commit_msg>debug container<commit_after>package main

import (
    "fmt"
    "strconv"
    "strings"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/ecs"
)

type Plugin struct {
    Key                     string
    Secret                  string
    Region                  string
    Family                  string
    TaskRoleArn             string
    Service                 string
    ContainerName           string
    DockerImage             string
    Tag                     string
    Cluster                 string
    DeploymentConfiguration string
    LogDriver               string
    LogOptions              []string
    PortMappings            []string
    DockerLabels            []string
    Environment             []string
    DesiredCount            int64
    CPU                     int64
    Memory                  int64
    MemoryReservation       int64
    YamlVerified            bool
}

func (p *Plugin) Exec() error {
    fmt.Println("Drone AWS ECS Plugin built")
    awsConfig := aws.Config{}

    if len(p.Key) != 0 && len(p.Secret) != 0 {
        awsConfig.Credentials = credentials.NewStaticCredentials(p.Key, p.Secret, "")
    }
    awsConfig.Region = aws.String(p.Region)
    svc := ecs.New(session.New(&awsConfig))

    Image := p.DockerImage + ":" + p.Tag
    if len(p.ContainerName) == 0 {
        p.ContainerName = p.Family + "-container"
    }

    definition := ecs.ContainerDefinition{
        Command: []*string{},

        DnsSearchDomains:      []*string{},
        DnsServers:            []*string{},
        DockerLabels:          map[string]*string{},
        DockerSecurityOptions: []*string{},
        EntryPoint:            []*string{},
        Environment:           []*ecs.KeyValuePair{},
        Essential:             aws.Bool(true),
        ExtraHosts:            []*ecs.HostEntry{},

        Image:        aws.String(Image),
        Links:        []*string{},
        Memory:       aws.Int64(p.Memory),
        MountPoints:  []*ecs.MountPoint{},
        Name:         aws.String(p.ContainerName),
        PortMappings: []*ecs.PortMapping{},

        Ulimits: []*ecs.Ulimit{},
        //User: aws.String("String"),
        VolumesFrom: []*ecs.VolumeFrom{},
        //WorkingDirectory: aws.String("String"),
    }

    if p.CPU != 0 {
        definition.Cpu = aws.Int64(p.CPU)
    }

    if p.Memory == 0 && p.MemoryReservation == 0 {
        definition.MemoryReservation = aws.Int64(128)
    } else {
        if p.Memory != 0 {
            definition.Memory = aws.Int64(p.Memory)
        }
        if p.MemoryReservation != 0 {
            definition.MemoryReservation = aws.Int64(p.MemoryReservation)
        }
    }

    // Port mappings
    for _, portMapping := range p.PortMappings {
        cleanedPortMapping := strings.Trim(portMapping, " ")
        parts := strings.SplitN(cleanedPortMapping, " ", 2)
        hostPort, hostPortErr := strconv.ParseInt(parts[0], 10, 64)
        if hostPortErr != nil {
            fmt.Println(hostPortErr.Error())
            return hostPortErr
        }
        containerPort, containerPortError := strconv.ParseInt(parts[1], 10, 64)
        if containerPortError != nil {
            fmt.Println(containerPortError.Error())
            return containerPortError
        }

        pair := ecs.PortMapping{
            ContainerPort: aws.Int64(containerPort),
            HostPort:      aws.Int64(hostPort),
            Protocol:      aws.String("TransportProtocol"),
        }

        definition.PortMappings = append(definition.PortMappings, &pair)
    }

    // Environment variables
    for _, envVar := range p.Environment {
        parts := strings.SplitN(envVar, "=", 2)
        pair := ecs.KeyValuePair{
            Name:  aws.String(strings.Trim(parts[0], " ")),
            Value: aws.String(strings.Trim(parts[1], " ")),
        }
        definition.Environment = append(definition.Environment, &pair)
    }

    // DockerLabels
    for _, label := range p.DockerLabels {
        parts := strings.SplitN(label, "=", 2)
        definition.DockerLabels[strings.Trim(parts[0], " ")] = aws.String(strings.Trim(parts[1], " "))
    }

    // LogOptions
    if len(p.LogDriver) > 0 {
        definition.LogConfiguration = new(ecs.LogConfiguration)
        definition.LogConfiguration.LogDriver = &p.LogDriver
        if len(p.LogOptions) > 0 {
            definition.LogConfiguration.Options = make(map[string]*string)
            for _, logOption := range p.LogOptions {
                parts := strings.SplitN(logOption, "=", 2)
                logOptionKey := strings.Trim(parts[0], " ")
                logOptionValue := aws.String(strings.Trim(parts[1], " "))
                definition.LogConfiguration.Options[logOptionKey] = logOptionValue
            }
        }
    }

    params := &ecs.RegisterTaskDefinitionInput{
        ContainerDefinitions: []*ecs.ContainerDefinition{
            &definition,
        },
        Family:      aws.String(p.Family),
        Volumes:     []*ecs.Volume{},
        TaskRoleArn: aws.String(p.TaskRoleArn),
    }
    resp, err := svc.RegisterTaskDefinition(params)

    if err != nil {
        fmt.Println(err.Error())
        return err
    }

    val := *(resp.TaskDefinition.TaskDefinitionArn)
    sparams := &ecs.UpdateServiceInput{
        Cluster:        aws.String(p.Cluster),
        Service:        aws.String(p.Service),
        TaskDefinition: aws.String(val),
    }

    if p.DesiredCount != 0 {
        sparams.DesiredCount = aws.Int64(p.DesiredCount)
    }

    // DeploymentConfiguration
    cleanedDeploymentConfiguration := strings.Trim(p.DeploymentConfiguration, " ")
    parts := strings.SplitN(cleanedDeploymentConfiguration, " ", 2)
    if len(parts) > 1 {
        minimumHealthyPercent, minimumHealthyPercentError := strconv.ParseInt(parts[0], 10, 64)
        if minimumHealthyPercentError != nil {
            fmt.Println(minimumHealthyPercentError.Error())
            return minimumHealthyPercentError
        }
        maximumPercent, maximumPercentErr := strconv.ParseInt(parts[1], 10, 64)
        if maximumPercentErr != nil {
            fmt.Println(maximumPercentErr.Error())
            return maximumPercentErr
        }

        sparams.DeploymentConfiguration = &ecs.DeploymentConfiguration{
            MaximumPercent:        aws.Int64(maximumPercent),
            MinimumHealthyPercent: aws.Int64(minimumHealthyPercent),
        }
    }

    sresp, serr := svc.UpdateService(sparams)

    if serr != nil {
        fmt.Println(serr.Error())
        return serr
    }

    fmt.Println(sresp)

    fmt.Println(resp)
    return nil

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"

	"flag"

	"os/signal"

	"github.com/cloudfoundry/cli/plugin"
	"github.com/tcnksm/go-input"
)

// Exit codes are int values that represent an exit code
// for a particular error.
const (
	ExitCodeOK    int = 0
	ExitCodeError int = 1 + iota
)

// EnvDebug is environmental variable for enabling debug
// output
const EnvDebug = "DEBUG_PLUGIN"

const (
	// DefaultPort is default port number
	DefaultPort = "8080"

	// DefaultImageName
	DefaultImageName = "cf-local-push"

	// Dockerfile is file name of Dockerfile
	Dockerfile = "Dockerfile"
)

// dockerfileText is used for build docker image for target application.
var dockerfileText = `FROM tcnksm/cf-buildstep:latest
ENV USER vcap
ADD . /app
RUN /build/builder
CMD /start web`

// Debugf prints debug output when EnvDebug is given
func Debugf(format string, args ...interface{}) {
	if env := os.Getenv(EnvDebug); len(env) != 0 {
		fmt.Fprintf(os.Stdout, "[DEBUG] "+format+"\n", args...)
	}
}

// LocalPush
type LocalPush struct {
	OutStream io.Writer
	InStream  io.Reader
}

// Run starts plugin process.
func (p *LocalPush) Run(cliConn plugin.CliConnection, arg []string) {
	Debugf("Run local-push plugin")
	Debugf("Arg: %#v", arg)

	// Ensure local-push is called.
	// Plugin is also called when install/uninstall via cf command.
	// Ignore such other calls.
	if len(arg) < 1 || arg[0] != Name {
		os.Exit(ExitCodeOK)
	}

	// Read CLI context (Currently, ctx val is not used but in future it should).
	ctx, err := NewCLIContext(cliConn)
	if err != nil {
		fmt.Fprintf(p.OutStream, "Failed to read cf command context: %s\n", err)
		os.Exit(ExitCodeError)
	}

	// Call run instead of doing the work here so we can use
	// `defer` statements within the function and have them work properly.
	// (defers aren't called with os.Exit)
	os.Exit(p.run(ctx, arg[1:]))
}

// run runs local-push it returns exit code.
func (p *LocalPush) run(ctx *CLIContext, args []string) int {

	var (
		port  string
		image string

		version bool
	)

	flags := flag.NewFlagSet("plugin", flag.ContinueOnError)
	flags.SetOutput(p.OutStream)
	flags.Usage = func() {
		fmt.Fprintln(p.OutStream, p.Usage())
	}

	flags.StringVar(&port, "port", DefaultPort, "")
	flags.StringVar(&port, "p", DefaultPort, "(Short)")

	flags.StringVar(&image, "image", DefaultImageName, "")
	flags.StringVar(&image, "i", DefaultImageName, "(Short)")

	flags.BoolVar(&version, "version", false, "")
	flags.BoolVar(&version, "v", false, "(Short)")

	if err := flags.Parse(args); err != nil {
		return ExitCodeError
	}

	if version {
		var buf bytes.Buffer
		fmt.Fprintf(&buf, "%s v%s", Name, VersionStr())

		if len(GitCommit) != 0 {
			fmt.Fprintf(&buf, " (%s)", GitCommit)
		}

		fmt.Fprintln(p.OutStream, buf.String())
		return ExitCodeOK
	}

	ui := &input.UI{
		Writer: p.OutStream,
		Reader: p.InStream,
	}

	// Check docker is installed or not.
	if _, err := exec.LookPath("docker"); err != nil {
		fmt.Fprintf(p.OutStream, "docker command is not found in your $PATH. Install it before.\n")
		return ExitCodeError
	}

	// Check Dockerfile is exist or not.
	// If it's exist, ask user to overwriting.
	if _, err := os.Stat(Dockerfile); !os.IsNotExist(err) {
		fmt.Fprintf(p.OutStream, "Dockerfile is already exist\n")
		query := "Overwrite Dockerfile? [yN]"
		ans, err := ui.Ask(query, &input.Options{
			Default:     "N",
			HideDefault: true,
			HideOrder:   true,
			Required:    true,
			Loop:        true,
			ValidateFunc: func(s string) error {
				if s != "y" && s != "N" {
					return fmt.Errorf("input must be 'y' or 'N'")
				}
				return nil
			},
		})

		if err != nil {
			fmt.Fprintf(p.OutStream, "Failed to read input: %s\n", err)
			return ExitCodeError
		}

		// Stop execution
		if ans != "y" {
			fmt.Fprintf(p.OutStream, "Aborting\n")
			return ExitCodeOK
		}
	}

	fmt.Fprintf(p.OutStream, "(cf-local-push) Generate Dockerfile\n")
	f, err := os.Create("Dockerfile")
	if err != nil {
		fmt.Fprintf(p.OutStream, "%s\n", err)
		return ExitCodeError
	}

	if _, err := f.Write([]byte(dockerfileText)); err != nil {
		fmt.Fprintf(p.OutStream, "%s\n", err)
		return ExitCodeError
	}

	fmt.Fprintf(p.OutStream, "(cf-local-push) Start building docker image\n")

	docker := &Docker{
		OutStream: p.OutStream,
		Discard:   false,
	}

	if err := docker.execute("build", "-t", image, "."); err != nil {
		fmt.Fprintf(p.OutStream, "%s\n", err)
		return ExitCodeError
	}

	fmt.Fprintf(p.OutStream, "(cf-local-push) Start running docker container\n")

	// errCh
	errCh := make(chan error, 1)

	// port mapping settings
	portMap := fmt.Sprintf("%s:%s", port, port)
	portEnv := fmt.Sprintf("PORT=%s", port)
	portEnvVcap := fmt.Sprintf("VCAP_APP_PORT=%s", port)

	// Use same name as image
	container := image

	go func() {
		Debugf("Run command: docker run -p %s -e %s -e %s--name %s %s",
			portMap, portEnv, portEnvVcap, container, image)
		errCh <- docker.execute("run",
			"-p", portMap,
			"-e", portEnv,
			"-e", portEnvVcap,
			"--name", container,
			image)
	}()

	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, os.Interrupt)

	select {
	case <-sigCh:
		fmt.Fprintf(p.OutStream, "Interrupt: Stop and remove container (It takes a few seconds...")

		// Don't output
		docker.Discard = true

		// Stop & Remove docker container
		docker.execute("stop", container)
		docker.execute("rm", container)

		return ExitCodeOK
	case err := <-errCh:
		if err != nil {
			fmt.Fprintf(p.OutStream, "Failed to run container %s: %s\n", container, err)
			return ExitCodeError
		}
		return ExitCodeOK
	}
}

func (p *LocalPush) GetMetadata() plugin.PluginMetadata {
	return plugin.PluginMetadata{
		Name:    Name,
		Version: Version,
		Commands: []plugin.Command{
			{
				Name:     "local-push",
				HelpText: "Push cf app on local Docker container",
				UsageDetails: plugin.Usage{
					Usage: p.Usage(),
				},
			},
		},
	}
}

func (p *LocalPush) Usage() string {
	text := `cf local-push [options]

local-push command tells cf to deploy current working directory app on
local docker container. You need to prepare docker environment before.

local-push remove the container after stop the container.

Options:

  -port PORT      Port number to map to docker container. You can access
                  to application via this port. By default, '8080' is used.
                  If you use, docker machine for running docker, you can
                  access application by 'curl $(docker-machine ip):PORT)'.

  -image NAME     Docker image name. By default, 'local-push' is used.

  -version        Show version and quit.

`
	return text
}
<commit_msg>Fix imports<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/signal"

	"github.com/cloudfoundry/cli/plugin"
	"github.com/tcnksm/go-input"
)

// Exit codes are int values that represent an exit code
// for a particular error.
const (
	ExitCodeOK    int = 0
	ExitCodeError int = 1 + iota
)

// EnvDebug is environmental variable for enabling debug
// output
const EnvDebug = "DEBUG_PLUGIN"

const (
	// DefaultPort is default port number
	DefaultPort = "8080"

	// DefaultImageName
	DefaultImageName = "cf-local-push"

	// Dockerfile is file name of Dockerfile
	Dockerfile = "Dockerfile"
)

// dockerfileText is used for build docker image for target application.
var dockerfileText = `FROM tcnksm/cf-buildstep:latest
ENV USER vcap
ADD . /app
RUN /build/builder
CMD /start web`

// Debugf prints debug output when EnvDebug is given
func Debugf(format string, args ...interface{}) {
	if env := os.Getenv(EnvDebug); len(env) != 0 {
		fmt.Fprintf(os.Stdout, "[DEBUG] "+format+"\n", args...)
	}
}

// LocalPush
type LocalPush struct {
	OutStream io.Writer
	InStream  io.Reader
}

// Run starts plugin process.
func (p *LocalPush) Run(cliConn plugin.CliConnection, arg []string) {
	Debugf("Run local-push plugin")
	Debugf("Arg: %#v", arg)

	// Ensure local-push is called.
	// Plugin is also called when install/uninstall via cf command.
	// Ignore such other calls.
	if len(arg) < 1 || arg[0] != Name {
		os.Exit(ExitCodeOK)
	}

	// Read CLI context (Currently, ctx val is not used but in future it should).
	ctx, err := NewCLIContext(cliConn)
	if err != nil {
		fmt.Fprintf(p.OutStream, "Failed to read cf command context: %s\n", err)
		os.Exit(ExitCodeError)
	}

	// Call run instead of doing the work here so we can use
	// `defer` statements within the function and have them work properly.
	// (defers aren't called with os.Exit)
	os.Exit(p.run(ctx, arg[1:]))
}

// run runs local-push it returns exit code.
func (p *LocalPush) run(ctx *CLIContext, args []string) int {

	var (
		port  string
		image string

		version bool
	)

	flags := flag.NewFlagSet("plugin", flag.ContinueOnError)
	flags.SetOutput(p.OutStream)
	flags.Usage = func() {
		fmt.Fprintln(p.OutStream, p.Usage())
	}

	flags.StringVar(&port, "port", DefaultPort, "")
	flags.StringVar(&port, "p", DefaultPort, "(Short)")

	flags.StringVar(&image, "image", DefaultImageName, "")
	flags.StringVar(&image, "i", DefaultImageName, "(Short)")

	flags.BoolVar(&version, "version", false, "")
	flags.BoolVar(&version, "v", false, "(Short)")

	if err := flags.Parse(args); err != nil {
		return ExitCodeError
	}

	if version {
		var buf bytes.Buffer
		fmt.Fprintf(&buf, "%s v%s", Name, VersionStr())

		if len(GitCommit) != 0 {
			fmt.Fprintf(&buf, " (%s)", GitCommit)
		}

		fmt.Fprintln(p.OutStream, buf.String())
		return ExitCodeOK
	}

	ui := &input.UI{
		Writer: p.OutStream,
		Reader: p.InStream,
	}

	// Check docker is installed or not.
	if _, err := exec.LookPath("docker"); err != nil {
		fmt.Fprintf(p.OutStream, "docker command is not found in your $PATH. Install it before.\n")
		return ExitCodeError
	}

	// Check Dockerfile is exist or not.
	// If it's exist, ask user to overwriting.
	if _, err := os.Stat(Dockerfile); !os.IsNotExist(err) {
		fmt.Fprintf(p.OutStream, "Dockerfile is already exist\n")
		query := "Overwrite Dockerfile? [yN]"
		ans, err := ui.Ask(query, &input.Options{
			Default:     "N",
			HideDefault: true,
			HideOrder:   true,
			Required:    true,
			Loop:        true,
			ValidateFunc: func(s string) error {
				if s != "y" && s != "N" {
					return fmt.Errorf("input must be 'y' or 'N'")
				}
				return nil
			},
		})

		if err != nil {
			fmt.Fprintf(p.OutStream, "Failed to read input: %s\n", err)
			return ExitCodeError
		}

		// Stop execution
		if ans != "y" {
			fmt.Fprintf(p.OutStream, "Aborting\n")
			return ExitCodeOK
		}
	}

	fmt.Fprintf(p.OutStream, "(cf-local-push) Generate Dockerfile\n")
	f, err := os.Create("Dockerfile")
	if err != nil {
		fmt.Fprintf(p.OutStream, "%s\n", err)
		return ExitCodeError
	}

	if _, err := f.Write([]byte(dockerfileText)); err != nil {
		fmt.Fprintf(p.OutStream, "%s\n", err)
		return ExitCodeError
	}

	fmt.Fprintf(p.OutStream, "(cf-local-push) Start building docker image\n")

	docker := &Docker{
		OutStream: p.OutStream,
		Discard:   false,
	}

	if err := docker.execute("build", "-t", image, "."); err != nil {
		fmt.Fprintf(p.OutStream, "%s\n", err)
		return ExitCodeError
	}

	fmt.Fprintf(p.OutStream, "(cf-local-push) Start running docker container\n")

	// errCh
	errCh := make(chan error, 1)

	// port mapping settings
	portMap := fmt.Sprintf("%s:%s", port, port)
	portEnv := fmt.Sprintf("PORT=%s", port)
	portEnvVcap := fmt.Sprintf("VCAP_APP_PORT=%s", port)

	// Use same name as image
	container := image

	go func() {
		Debugf("Run command: docker run -p %s -e %s -e %s--name %s %s",
			portMap, portEnv, portEnvVcap, container, image)
		errCh <- docker.execute("run",
			"-p", portMap,
			"-e", portEnv,
			"-e", portEnvVcap,
			"--name", container,
			image)
	}()

	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, os.Interrupt)

	select {
	case <-sigCh:
		fmt.Fprintf(p.OutStream, "Interrupt: Stop and remove container (It takes a few seconds...")

		// Don't output
		docker.Discard = true

		// Stop & Remove docker container
		docker.execute("stop", container)
		docker.execute("rm", container)

		return ExitCodeOK
	case err := <-errCh:
		if err != nil {
			fmt.Fprintf(p.OutStream, "Failed to run container %s: %s\n", container, err)
			return ExitCodeError
		}
		return ExitCodeOK
	}
}

func (p *LocalPush) GetMetadata() plugin.PluginMetadata {
	return plugin.PluginMetadata{
		Name:    Name,
		Version: Version,
		Commands: []plugin.Command{
			{
				Name:     "local-push",
				HelpText: "Push cf app on local Docker container",
				UsageDetails: plugin.Usage{
					Usage: p.Usage(),
				},
			},
		},
	}
}

func (p *LocalPush) Usage() string {
	text := `cf local-push [options]

local-push command tells cf to deploy current working directory app on
local docker container. You need to prepare docker environment before.

local-push remove the container after stop the container.

Options:

  -port PORT      Port number to map to docker container. You can access
                  to application via this port. By default, '8080' is used.
                  If you use, docker machine for running docker, you can
                  access application by 'curl $(docker-machine ip):PORT)'.

  -image NAME     Docker image name. By default, 'local-push' is used.

  -version        Show version and quit.

`
	return text
}
<|endoftext|>


<commit_before>package alicloud

import (
	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/ecs"
	"github.com/denverdino/aliyungo/metadata"
	"github.com/denverdino/aliyungo/slb"
	"github.com/golang/glog"
	"github.com/patrickmn/go-cache"
	"k8s.io/apimachinery/pkg/util/wait"
	"sync"
	"time"
)

var ROLE_NAME = "KubernetesMasterRole"

var TOKEN_RESYNC_PERIOD = 5 * time.Minute

type TokenAuth struct {
	lock   sync.RWMutex
	auth   metadata.RoleAuth
	active bool
}

func (token *TokenAuth) authid() (string, string, string) {
	token.lock.RLock()
	defer token.lock.RUnlock()

	return token.auth.AccessKeyId,
		token.auth.AccessKeySecret,
		token.auth.SecurityToken
}

type ClientMgr struct {
	stop <-chan struct{}

	token *TokenAuth

	meta         *metadata.MetaData
	routes       *RoutesClient
	loadbalancer *LoadBalancerClient
	instance     *InstancerClient
}

func NewClientMgr(key, secret string) (*ClientMgr, error) {
	token := &TokenAuth{
		auth: metadata.RoleAuth{
			AccessKeyId:     key,
			AccessKeySecret: secret,
		},
		active: false,
	}
	m := metadata.NewMetaData(nil)

	if key == "" || secret == "" {
		if rolename, err := m.Role(); err != nil {
			return nil, err
		}else {
			ROLE_NAME = rolename
			role, err := m.RamRoleToken(ROLE_NAME)
			if err != nil {
				return nil, err
			}
			glog.V(2).Infof("alicloud: clientmgr, using role=[%s] with initial token=[%+v]",ROLE_NAME, role)
			token.auth = role
			token.active = true
		}
	}
	keyid, sec, tok := token.authid()
	ecsclient := ecs.NewClient(keyid, sec)
	ecsclient.SetSecurityToken(tok)
	ecsclient.SetUserAgent(KUBERNETES_ALICLOUD_IDENTITY)
	ecsclient.SetRegionID(DEFAULT_REGION)

	slbclient := slb.NewClient(keyid, sec)
	slbclient.SetSecurityToken(tok)
	slbclient.SetUserAgent(KUBERNETES_ALICLOUD_IDENTITY)
	slbclient.SetRegionID(DEFAULT_REGION)

	mgr := &ClientMgr{
		stop:  make(<-chan struct{}, 1),
		token: token,
		meta:  m,
		instance: &InstancerClient{
			c: ecsclient,
		},
		loadbalancer: &LoadBalancerClient{
			c: slbclient,
		},
		routes: &RoutesClient{
			client:  ecsclient,
			routers: cache.New(defaultCacheExpiration, defaultCacheExpiration),
			vpcs:    cache.New(defaultCacheExpiration, defaultCacheExpiration),
		},
	}
	if !token.active {
		// use key and secret
		glog.Infof("alicloud: clientmgr, use accesskeyid and accesskeysecret mode to authenticate user. without token")
		return mgr, nil
	}
	go wait.Until(func() {
		// refresh client token periodically
		token.lock.Lock()
		defer token.lock.Unlock()
		role, err := mgr.meta.RamRoleToken(ROLE_NAME)
		if err != nil {
			glog.Errorf("alicloud: clientmgr, error get ram role token [%s]\n", err.Error())
			return
		}
		token.auth = role
		ecsclient.WithSecurityToken(role.SecurityToken).
			WithAccessKeyId(role.AccessKeyId).
			WithAccessKeySecret(role.AccessKeySecret)
		slbclient.WithSecurityToken(role.SecurityToken).
			WithAccessKeyId(role.AccessKeyId).
			WithAccessKeySecret(role.AccessKeySecret)
	}, time.Duration(TOKEN_RESYNC_PERIOD), mgr.stop)

	return mgr, nil
}

func (c *ClientMgr) Instances(region common.Region) *InstancerClient {
	return c.instance
}

func (c *ClientMgr) Routes(region common.Region) *RoutesClient {
	return c.routes
}

func (c *ClientMgr) LoadBalancers(region common.Region) *LoadBalancerClient {
	return c.loadbalancer
}

func (c *ClientMgr) MetaData() *metadata.MetaData {

	return c.meta
}
<commit_msg>fix huabei3 slb create failed issue<commit_after>package alicloud

import (
	"sync"
	"time"

	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/ecs"
	"github.com/denverdino/aliyungo/metadata"
	"github.com/denverdino/aliyungo/slb"
	"github.com/golang/glog"
	"github.com/patrickmn/go-cache"
	"k8s.io/apimachinery/pkg/util/wait"
)

var ROLE_NAME = "KubernetesMasterRole"

var TOKEN_RESYNC_PERIOD = 5 * time.Minute

type TokenAuth struct {
	lock   sync.RWMutex
	auth   metadata.RoleAuth
	active bool
}

func (token *TokenAuth) authid() (string, string, string) {
	token.lock.RLock()
	defer token.lock.RUnlock()

	return token.auth.AccessKeyId,
		token.auth.AccessKeySecret,
		token.auth.SecurityToken
}

type ClientMgr struct {
	stop <-chan struct{}

	token *TokenAuth

	meta         *metadata.MetaData
	routes       *RoutesClient
	loadbalancer *LoadBalancerClient
	instance     *InstancerClient
}

func NewClientMgr(key, secret string) (*ClientMgr, error) {
	token := &TokenAuth{
		auth: metadata.RoleAuth{
			AccessKeyId:     key,
			AccessKeySecret: secret,
		},
		active: false,
	}
	m := metadata.NewMetaData(nil)

	if key == "" || secret == "" {
		if rolename, err := m.RoleName(); err != nil {
			return nil, err
		} else {
			ROLE_NAME = rolename
			role, err := m.RamRoleToken(ROLE_NAME)
			if err != nil {
				return nil, err
			}
			glog.V(2).Infof("alicloud: clientmgr, using role=[%s] with initial token=[%+v]", ROLE_NAME, role)
			token.auth = role
			token.active = true
		}
	}
	keyid, sec, tok := token.authid()
	ecsclient := ecs.NewECSClientWithSecurityToken(keyid, sec, tok, DEFAULT_REGION)
	ecsclient.SetUserAgent(KUBERNETES_ALICLOUD_IDENTITY)
	slbclient := slb.NewSLBClientWithSecurityToken(keyid, sec, tok, DEFAULT_REGION)
	slbclient.SetUserAgent(KUBERNETES_ALICLOUD_IDENTITY)

	mgr := &ClientMgr{
		stop:  make(<-chan struct{}, 1),
		token: token,
		meta:  m,
		instance: &InstancerClient{
			c: ecsclient,
		},
		loadbalancer: &LoadBalancerClient{
			c: slbclient,
		},
		routes: &RoutesClient{
			client:  ecsclient,
			routers: cache.New(defaultCacheExpiration, defaultCacheExpiration),
			vpcs:    cache.New(defaultCacheExpiration, defaultCacheExpiration),
		},
	}
	if !token.active {
		// use key and secret
		glog.Infof("alicloud: clientmgr, use accesskeyid and accesskeysecret mode to authenticate user. without token")
		return mgr, nil
	}
	go wait.Until(func() {
		// refresh client token periodically
		token.lock.Lock()
		defer token.lock.Unlock()
		role, err := mgr.meta.RamRoleToken(ROLE_NAME)
		if err != nil {
			glog.Errorf("alicloud: clientmgr, error get ram role token [%s]\n", err.Error())
			return
		}
		token.auth = role
		ecsclient.WithSecurityToken(role.SecurityToken).
			WithAccessKeyId(role.AccessKeyId).
			WithAccessKeySecret(role.AccessKeySecret)
		slbclient.WithSecurityToken(role.SecurityToken).
			WithAccessKeyId(role.AccessKeyId).
			WithAccessKeySecret(role.AccessKeySecret)
	}, time.Duration(TOKEN_RESYNC_PERIOD), mgr.stop)

	return mgr, nil
}

func (c *ClientMgr) Instances(region common.Region) *InstancerClient {
	return c.instance
}

func (c *ClientMgr) Routes(region common.Region) *RoutesClient {
	return c.routes
}

func (c *ClientMgr) LoadBalancers(region common.Region) *LoadBalancerClient {
	return c.loadbalancer
}

func (c *ClientMgr) MetaData() *metadata.MetaData {

	return c.meta
}
<|endoftext|>


<commit_before>// Package middlewares provides common middleware handlers.
package middlewares

import (
	// "fmt"
	"github.com/GeertJohan/go.rice"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"github.com/jmoiron/sqlx"
	resourcedmaster_dal "github.com/resourced/resourced-master/dal"
	"github.com/resourced/resourced-master/libhttp"
	"net/http"
)

func SetDB(db *sqlx.DB) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
			context.Set(req, "db", db)

			next.ServeHTTP(res, req)
		})
	}
}

func SetRiceBoxes(riceBoxes map[string]*rice.Box) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
			context.Set(req, "riceBoxes", riceBoxes)

			next.ServeHTTP(res, req)
		})
	}
}

func SetCookieStore(cookieStore *sessions.CookieStore) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
			context.Set(req, "cookieStore", cookieStore)

			next.ServeHTTP(res, req)
		})
	}
}

// MustLogin is a middleware that checks existence of current user.
func MustLogin(next http.Handler) http.Handler {
	return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		cookieStore := context.Get(req, "cookieStore").(*sessions.CookieStore)
		session, _ := cookieStore.Get(req, "resourcedmaster-session")
		userRowInterface := session.Values["user"]

		if userRowInterface == nil {
			http.Redirect(res, req, "/login", 301)
			return
		}

		next.ServeHTTP(res, req)
	})
}

// MustLoginApi is a middleware that checks /api login.
func MustLoginApi(next http.Handler) http.Handler {
	return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")

		if auth == "" {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		accessTokenString, _, ok := libhttp.ParseBasicAuth(auth)
		if !ok {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		db := context.Get(req, "db").(*sqlx.DB)

		accessTokenRow, err := resourcedmaster_dal.NewAccessToken(db).GetByAccessToken(nil, accessTokenString)
		if err != nil {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}
		if accessTokenRow == nil {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		context.Set(req, "accessTokenRow", accessTokenRow)

		next.ServeHTTP(res, req)
	})
}
<commit_msg>MustLoginApi checks accesToken levels.<commit_after>// Package middlewares provides common middleware handlers.
package middlewares

import (
	// "fmt"
	"github.com/GeertJohan/go.rice"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"github.com/jmoiron/sqlx"
	resourcedmaster_dal "github.com/resourced/resourced-master/dal"
	"github.com/resourced/resourced-master/libhttp"
	"net/http"
)

func SetDB(db *sqlx.DB) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
			context.Set(req, "db", db)

			next.ServeHTTP(res, req)
		})
	}
}

func SetRiceBoxes(riceBoxes map[string]*rice.Box) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
			context.Set(req, "riceBoxes", riceBoxes)

			next.ServeHTTP(res, req)
		})
	}
}

func SetCookieStore(cookieStore *sessions.CookieStore) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
			context.Set(req, "cookieStore", cookieStore)

			next.ServeHTTP(res, req)
		})
	}
}

// MustLogin is a middleware that checks existence of current user.
func MustLogin(next http.Handler) http.Handler {
	return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		cookieStore := context.Get(req, "cookieStore").(*sessions.CookieStore)
		session, _ := cookieStore.Get(req, "resourcedmaster-session")
		userRowInterface := session.Values["user"]

		if userRowInterface == nil {
			http.Redirect(res, req, "/login", 301)
			return
		}

		next.ServeHTTP(res, req)
	})
}

// MustLoginApi is a middleware that checks /api login.
func MustLoginApi(next http.Handler) http.Handler {
	return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")

		if auth == "" {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		accessTokenString, _, ok := libhttp.ParseBasicAuth(auth)
		if !ok {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		db := context.Get(req, "db").(*sqlx.DB)

		accessTokenRow, err := resourcedmaster_dal.NewAccessToken(db).GetByAccessToken(nil, accessTokenString)
		if err != nil {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}
		if accessTokenRow == nil {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		isAllowed := false

		if req.Method == "GET" {
			isAllowed = true
		} else if accessTokenRow.Level == "write" || accessTokenRow.Level == "execute" {
			isAllowed = true
		}

		if !isAllowed {
			libhttp.BasicAuthUnauthorized(res, nil)
			return
		}

		context.Set(req, "accessTokenRow", accessTokenRow)

		next.ServeHTTP(res, req)
	})
}
<|endoftext|>


<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package lang

import (
	"encoding/json"

	gm "github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/util"
	"github.com/sourcegraph/go-langserver/pkg/lsp"
	"github.com/sourcegraph/jsonrpc2"
)

type stubImpl struct {
	ImplementationFilePath string   `json:"implementationFilePath"`
	Codes                  []string `json:"codes"`
}

func getImplFiles(req *jsonrpc2.Request) (interface{}, error) {
	var info = struct {
		Concept bool `json:"concept"`
	}{}
	if err := json.Unmarshal(*req.Params, &info); err != nil {
		logger.APILog.Debugf("failed to parse request %s", err.Error())
		return nil, err
	}
	if info.Concept {
		return util.GetConceptFiles(), nil
	}
	implementationFileListResponse, err := getImplementationFileList()
	if err != nil {
		return nil, err
	}
	return implementationFileListResponse.ImplementationFilePaths, nil
}

func putStubImpl(req *jsonrpc2.Request) (interface{}, error) {
	var stubImplParams stubImpl
	if err := json.Unmarshal(*req.Params, &stubImplParams); err != nil {
		logger.APILog.Debugf("failed to parse request %s", err.Error())
		return nil, err
	}
	fileDiff, err := putStubImplementation(stubImplParams.ImplementationFilePath, stubImplParams.Codes)
	if err != nil {
		return nil, err
	}

	return getWorkspaceEditForStubImpl(fileDiff), nil
}

func getWorkspaceEditForStubImpl(fileDiff *gm.FileDiff) lsp.WorkspaceEdit {
	var result lsp.WorkspaceEdit
	result.Changes = make(map[string][]lsp.TextEdit, 0)
	uri := util.ConvertPathToURI(lsp.DocumentURI(fileDiff.FilePath))

	var textDiffs = fileDiff.TextDiffs
	for _, textDiff := range textDiffs {
		textEdit := lsp.TextEdit{
			NewText: textDiff.Content,
			Range: lsp.Range{
				Start: lsp.Position{Line: int(textDiff.Span.Start), Character: int(textDiff.Span.StartChar)},
				End:   lsp.Position{Line: int(textDiff.Span.End), Character: int(textDiff.Span.EndChar)},
			},
		}
		result.Changes[string(uri)] = append(result.Changes[string(uri)], textEdit)
	}
	return result
}
<commit_msg>Using fmt instead of logger<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package lang

import (
	"encoding/json"
	"fmt"

	gm "github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/util"
	"github.com/sourcegraph/go-langserver/pkg/lsp"
	"github.com/sourcegraph/jsonrpc2"
)

type stubImpl struct {
	ImplementationFilePath string   `json:"implementationFilePath"`
	Codes                  []string `json:"codes"`
}

func getImplFiles(req *jsonrpc2.Request) (interface{}, error) {
	var info = struct {
		Concept bool `json:"concept"`
	}{}
	if err := json.Unmarshal(*req.Params, &info); err != nil {
		return nil, fmt.Errorf("failed to parse request %s", err.Error())
	}
	if info.Concept {
		return util.GetConceptFiles(), nil
	}
	implementationFileListResponse, err := getImplementationFileList()
	if err != nil {
		return nil, err
	}
	return implementationFileListResponse.ImplementationFilePaths, nil
}

func putStubImpl(req *jsonrpc2.Request) (interface{}, error) {
	var stubImplParams stubImpl
	if err := json.Unmarshal(*req.Params, &stubImplParams); err != nil {
		return nil, fmt.Errorf("failed to parse request %s", err.Error())
	}
	fileDiff, err := putStubImplementation(stubImplParams.ImplementationFilePath, stubImplParams.Codes)
	if err != nil {
		return nil, err
	}

	return getWorkspaceEditForStubImpl(fileDiff), nil
}

func getWorkspaceEditForStubImpl(fileDiff *gm.FileDiff) lsp.WorkspaceEdit {
	var result lsp.WorkspaceEdit
	result.Changes = make(map[string][]lsp.TextEdit, 0)
	uri := util.ConvertPathToURI(lsp.DocumentURI(fileDiff.FilePath))

	var textDiffs = fileDiff.TextDiffs
	for _, textDiff := range textDiffs {
		textEdit := lsp.TextEdit{
			NewText: textDiff.Content,
			Range: lsp.Range{
				Start: lsp.Position{Line: int(textDiff.Span.Start), Character: int(textDiff.Span.StartChar)},
				End:   lsp.Position{Line: int(textDiff.Span.End), Character: int(textDiff.Span.EndChar)},
			},
		}
		result.Changes[string(uri)] = append(result.Changes[string(uri)], textEdit)
	}
	return result
}
<|endoftext|>


<commit_before>package main

const Name string = "lc"
const Version string = "0.2.0"
<commit_msg>update version to 0.2.1<commit_after>package main

const Name string = "lc"
const Version string = "0.2.1"
<|endoftext|>


<commit_before>package credential

// TODO: properly comment all data structures and functions
import (
	"errors"
	"math/big"
)

// Proof represents a non-interactive zero-knowledge proof
type Proof interface {
	VerifyWithChallenge(pk *PublicKey, reconstructedChallenge *big.Int) bool
	SecretKeyResponse() *big.Int
	ChallengeContribution(pk *PublicKey) []*big.Int
}

// createChallenge creates a challenge based on context, nonce and the
// contributions.
func createChallenge(context, nonce *big.Int, contributions []*big.Int) *big.Int {
	// Basically, sandwich the contributions between context and nonce
	input := make([]*big.Int, 2+len(contributions))
	input[0] = context
	copy(input[1:1+len(contributions)], contributions)
	input[len(input)-1] = nonce
	return hashCommit(input)
}

// ProofU represents a proof of correctness of the commitment in the first phase
// of the issuance protocol.
type ProofU struct {
	u              *big.Int
	c              *big.Int
	vPrimeResponse *big.Int
	sResponse      *big.Int
}

// Verify verifies whether the proof is correct.
func (p *ProofU) Verify(pk *PublicKey, context, nonce *big.Int) bool {
	return p.VerifyWithChallenge(pk, createChallenge(context, nonce, p.ChallengeContribution(pk)))
}

func (p *ProofU) correctResponseSizes(pk *PublicKey) bool {
	maximum := new(big.Int).Lsh(bigONE, pk.Params.LvPrimeCommit+1)
	maximum.Sub(maximum, bigONE)
	minimum := new(big.Int).Neg(maximum)

	return p.vPrimeResponse.Cmp(minimum) >= 0 && p.vPrimeResponse.Cmp(maximum) <= 0
}

// Verify verifies whether the proof is correct.
func (p *ProofU) VerifyWithChallenge(pk *PublicKey, reconstructedChallenge *big.Int) bool {
	return p.correctResponseSizes(pk) && p.c.Cmp(reconstructedChallenge) == 0
}

func (p *ProofU) reconstructUcommit(pk *PublicKey) *big.Int {
	// Reconstruct Ucommit
	// U_commit = U^{-c} * S^{vPrimeResponse} * R_0^{sResponse}
	Uc := modPow(p.u, new(big.Int).Neg(p.c), &pk.N)
	Sv := modPow(&pk.S, p.vPrimeResponse, &pk.N)
	R0s := modPow(pk.R[0], p.sResponse, &pk.N)
	Ucommit := new(big.Int).Mul(Uc, Sv)
	Ucommit.Mul(Ucommit, R0s).Mod(Ucommit, &pk.N)

	return Ucommit
}

func (p *ProofU) SecretKeyResponse() *big.Int {
	return p.sResponse
}

func (p *ProofU) Challenge() *big.Int {
	return p.c
}

func (p *ProofU) ChallengeContribution(pk *PublicKey) []*big.Int {
	return []*big.Int{p.u, p.reconstructUcommit(pk)}
}

// ProofS represents a proof.
type ProofS struct {
	c         *big.Int
	eResponse *big.Int
}

// Verify verifies the proof agains the given public key, signature, context,
// and nonce.
func (p *ProofS) Verify(pk *PublicKey, signature *CLSignature, context, nonce *big.Int) bool {
	// Reconstruct A_commit
	// ACommit = A^{c + eResponse * e}
	exponent := new(big.Int).Mul(p.eResponse, signature.E)
	exponent.Add(p.c, exponent)
	ACommit := new(big.Int).Exp(signature.A, exponent, &pk.N)

	// Reconstruct Q
	Q := new(big.Int).Exp(signature.A, signature.E, &pk.N)

	// Recalculate hash
	cPrime := hashCommit([]*big.Int{context, Q, signature.A, nonce, ACommit})

	return p.c.Cmp(cPrime) == 0
}

// ProofD represents a proof in the showing protocol.
type ProofD struct {
	c, A, eResponse, vResponse *big.Int
	aResponses, aDisclosed     map[int]*big.Int
}

func (p *ProofD) correctResponseSizes(pk *PublicKey) bool {
	// Check range on the aResponses
	maximum := new(big.Int).Lsh(bigONE, pk.Params.LmCommit+1)
	maximum.Sub(maximum, bigONE)
	minimum := new(big.Int).Neg(maximum)
	for _, aResponse := range p.aResponses {
		if aResponse.Cmp(minimum) < 0 || aResponse.Cmp(maximum) > 0 {
			return false
		}
	}

	// Check range eResponse
	maximum.Lsh(bigONE, pk.Params.LeCommit+1)
	maximum.Sub(maximum, bigONE)
	minimum.Neg(maximum)

	if p.eResponse.Cmp(minimum) < 0 || p.eResponse.Cmp(maximum) > 0 {
		return false
	}

	return true
}

// reconstructZ reconstructs Z from the information in the proof and the
// provided public key.
func (p *ProofD) reconstructZ(pk *PublicKey) *big.Int {
	// known = Z / ( prod_{disclosed} R_i^{a_i} * A^{2^{l_e - 1}} )
	numerator := new(big.Int).Lsh(bigONE, pk.Params.Le-1)
	numerator.Exp(p.A, numerator, &pk.N)
	for i, attribute := range p.aDisclosed {
		numerator.Mul(numerator, new(big.Int).Exp(pk.R[i], attribute, &pk.N))
	}

	known := new(big.Int).ModInverse(numerator, &pk.N)
	known.Mul(&pk.Z, known)

	knownC := modPow(known, new(big.Int).Neg(p.c), &pk.N)
	Ae := modPow(p.A, p.eResponse, &pk.N)
	Sv := modPow(&pk.S, p.vResponse, &pk.N)
	Rs := big.NewInt(1)
	for i, response := range p.aResponses {
		Rs.Mul(Rs, modPow(pk.R[i], response, &pk.N))
	}
	Z := new(big.Int).Mul(knownC, Ae)
	Z.Mul(Z, Rs).Mul(Z, Sv).Mod(Z, &pk.N)

	return Z
}

// Verify verifies the proof against the given public key, context, and nonce.
func (p *ProofD) Verify(pk *PublicKey, context, nonce1 *big.Int) bool {
	return p.VerifyWithChallenge(pk, createChallenge(context, nonce1, p.ChallengeContribution(pk)))
}

// Verify verifies the proof against the given public key and the reconstruted challenge.
func (p *ProofD) VerifyWithChallenge(pk *PublicKey, reconstructedChallenge *big.Int) bool {
	return p.correctResponseSizes(pk) && p.c.Cmp(reconstructedChallenge) == 0
}

func (p *ProofD) ChallengeContribution(pk *PublicKey) []*big.Int {
	return []*big.Int{p.A, p.reconstructZ(pk)}
}

func (p *ProofD) SecretKeyResponse() *big.Int {
	return p.aResponses[0]
}

func (p *ProofD) Challenge() *big.Int {
	return p.c
}

type ProofBuilder interface {
	Commit(skRandomizer *big.Int) []*big.Int
	CreateProof(challenge *big.Int) Proof
}

type ProofList []Proof

var (
	ErrMissingProofU = errors.New("Missing ProofU in ProofList, has a CredentialBuilder been added?")
)

// GetProofU returns the n'th ProofU in this proof list.
func (pl ProofList) GetProofU(n int) (*ProofU, error) {
	count := 0
	for _, proof := range pl {
		switch proof.(type) {
		case *ProofU:
			if count == n {
				return proof.(*ProofU), nil
			}
			count++
		}
	}
	return nil, ErrMissingProofU
}

// GetFirstProofU returns the first ProofU in this proof list
func (pl ProofList) GetFirstProofU() (*ProofU, error) {
	return pl.GetProofU(0)
}

func (pl ProofList) challengeContributions(publicKeys []*PublicKey, context, nonce *big.Int) []*big.Int {
	contributions := make([]*big.Int, 0, len(pl)*2)
	for i, proof := range pl {
		contributions = append(contributions, proof.ChallengeContribution(publicKeys[i])...)
	}
	return contributions
}

func (pl ProofList) Verify(publicKeys []*PublicKey, context, nonce *big.Int, shouldBeBound bool) bool {
	if len(pl) == 0 {
		return true
	}

	if len(pl) != len(publicKeys) {
		return false
	}

	if shouldBeBound {
		contributions := pl.challengeContributions(publicKeys, context, nonce)
		expectedChallenge := createChallenge(context, nonce, contributions)
		expectedSecretKeyResponse := pl[0].SecretKeyResponse()
		for i, proof := range pl {
			if expectedSecretKeyResponse.Cmp(proof.SecretKeyResponse()) != 0 ||
				!proof.VerifyWithChallenge(publicKeys[i], expectedChallenge) {
				return false
			}
		}
	} else {
		for i, proof := range pl {
			// if !proof.Verify(publicKeys[i], context, nonce) {
			if !proof.VerifyWithChallenge(publicKeys[i], createChallenge(context, nonce, proof.ChallengeContribution(publicKeys[i]))) {
				return false
			}
		}
	}

	return true
}

func BuildProofList(params *SystemParameters, context, nonce *big.Int, proofBuilders []ProofBuilder) ProofList {
	skCommitment, _ := randomBigInt(params.LmCommit)

	commitmentValues := make([]*big.Int, 0, len(proofBuilders)*2)
	for _, pb := range proofBuilders {
		commitmentValues = append(commitmentValues, pb.Commit(skCommitment)...)
	}

	// Create a shared challenge
	challenge := createChallenge(context, nonce, commitmentValues)

	proofs := make([]Proof, len(proofBuilders))
	// Now create proofs using this challenge
	for i, v := range proofBuilders {
		proofs[i] = v.CreateProof(challenge)
	}
	return proofs
}
<commit_msg>Cleanup of keys.go.<commit_after>package credential

import (
	"errors"
	"math/big"
)

// Proof represents a non-interactive zero-knowledge proof
type Proof interface {
	VerifyWithChallenge(pk *PublicKey, reconstructedChallenge *big.Int) bool
	SecretKeyResponse() *big.Int
	ChallengeContribution(pk *PublicKey) []*big.Int
}

// createChallenge creates a challenge based on context, nonce and the
// contributions.
func createChallenge(context, nonce *big.Int, contributions []*big.Int) *big.Int {
	// Basically, sandwich the contributions between context and nonce
	input := make([]*big.Int, 2+len(contributions))
	input[0] = context
	copy(input[1:1+len(contributions)], contributions)
	input[len(input)-1] = nonce
	return hashCommit(input)
}

// ProofU represents a proof of correctness of the commitment in the first phase
// of the issuance protocol.
type ProofU struct {
	u              *big.Int
	c              *big.Int
	vPrimeResponse *big.Int
	sResponse      *big.Int
}

// Verify verifies whether the proof is correct.
func (p *ProofU) Verify(pk *PublicKey, context, nonce *big.Int) bool {
	return p.VerifyWithChallenge(pk, createChallenge(context, nonce, p.ChallengeContribution(pk)))
}

// correctResponseSizes checks the sizes of the elements in the ProofU proof.
func (p *ProofU) correctResponseSizes(pk *PublicKey) bool {
	maximum := new(big.Int).Lsh(bigONE, pk.Params.LvPrimeCommit+1)
	maximum.Sub(maximum, bigONE)
	minimum := new(big.Int).Neg(maximum)

	return p.vPrimeResponse.Cmp(minimum) >= 0 && p.vPrimeResponse.Cmp(maximum) <= 0
}

// VerifyWithChallenge verifies whether the proof is correct.
func (p *ProofU) VerifyWithChallenge(pk *PublicKey, reconstructedChallenge *big.Int) bool {
	return p.correctResponseSizes(pk) && p.c.Cmp(reconstructedChallenge) == 0
}

// reconstructUcommit reconstructs U from the information in the proof and the
// provided public key.
func (p *ProofU) reconstructUcommit(pk *PublicKey) *big.Int {
	// Reconstruct Ucommit
	// U_commit = U^{-c} * S^{vPrimeResponse} * R_0^{sResponse}
	Uc := modPow(p.u, new(big.Int).Neg(p.c), &pk.N)
	Sv := modPow(&pk.S, p.vPrimeResponse, &pk.N)
	R0s := modPow(pk.R[0], p.sResponse, &pk.N)
	Ucommit := new(big.Int).Mul(Uc, Sv)
	Ucommit.Mul(Ucommit, R0s).Mod(Ucommit, &pk.N)

	return Ucommit
}

// SecretKeyResponse returns the secret key response (as part of Proof
// interface).
func (p *ProofU) SecretKeyResponse() *big.Int {
	return p.sResponse
}

// Challenge returns the challenge in the proof (part of the Proof interface).
func (p *ProofU) Challenge() *big.Int {
	return p.c
}

// ChallengeContribution returns the contribution of this proof to the
// challenge.
func (p *ProofU) ChallengeContribution(pk *PublicKey) []*big.Int {
	return []*big.Int{p.u, p.reconstructUcommit(pk)}
}

// ProofS represents a proof.
type ProofS struct {
	c         *big.Int
	eResponse *big.Int
}

// Verify verifies the proof agains the given public key, signature, context,
// and nonce.
func (p *ProofS) Verify(pk *PublicKey, signature *CLSignature, context, nonce *big.Int) bool {
	// Reconstruct A_commit
	// ACommit = A^{c + eResponse * e}
	exponent := new(big.Int).Mul(p.eResponse, signature.E)
	exponent.Add(p.c, exponent)
	ACommit := new(big.Int).Exp(signature.A, exponent, &pk.N)

	// Reconstruct Q
	Q := new(big.Int).Exp(signature.A, signature.E, &pk.N)

	// Recalculate hash
	cPrime := hashCommit([]*big.Int{context, Q, signature.A, nonce, ACommit})

	return p.c.Cmp(cPrime) == 0
}

// ProofD represents a proof in the showing protocol.
type ProofD struct {
	c, A, eResponse, vResponse *big.Int
	aResponses, aDisclosed     map[int]*big.Int
}

// correctResponseSizes checks the sizes of the elements in the ProofD proof.
func (p *ProofD) correctResponseSizes(pk *PublicKey) bool {
	// Check range on the aResponses
	maximum := new(big.Int).Lsh(bigONE, pk.Params.LmCommit+1)
	maximum.Sub(maximum, bigONE)
	minimum := new(big.Int).Neg(maximum)
	for _, aResponse := range p.aResponses {
		if aResponse.Cmp(minimum) < 0 || aResponse.Cmp(maximum) > 0 {
			return false
		}
	}

	// Check range eResponse
	maximum.Lsh(bigONE, pk.Params.LeCommit+1)
	maximum.Sub(maximum, bigONE)
	minimum.Neg(maximum)

	if p.eResponse.Cmp(minimum) < 0 || p.eResponse.Cmp(maximum) > 0 {
		return false
	}

	return true
}

// reconstructZ reconstructs Z from the information in the proof and the
// provided public key.
func (p *ProofD) reconstructZ(pk *PublicKey) *big.Int {
	// known = Z / ( prod_{disclosed} R_i^{a_i} * A^{2^{l_e - 1}} )
	numerator := new(big.Int).Lsh(bigONE, pk.Params.Le-1)
	numerator.Exp(p.A, numerator, &pk.N)
	for i, attribute := range p.aDisclosed {
		numerator.Mul(numerator, new(big.Int).Exp(pk.R[i], attribute, &pk.N))
	}

	known := new(big.Int).ModInverse(numerator, &pk.N)
	known.Mul(&pk.Z, known)

	knownC := modPow(known, new(big.Int).Neg(p.c), &pk.N)
	Ae := modPow(p.A, p.eResponse, &pk.N)
	Sv := modPow(&pk.S, p.vResponse, &pk.N)
	Rs := big.NewInt(1)
	for i, response := range p.aResponses {
		Rs.Mul(Rs, modPow(pk.R[i], response, &pk.N))
	}
	Z := new(big.Int).Mul(knownC, Ae)
	Z.Mul(Z, Rs).Mul(Z, Sv).Mod(Z, &pk.N)

	return Z
}

// Verify verifies the proof against the given public key, context, and nonce.
func (p *ProofD) Verify(pk *PublicKey, context, nonce1 *big.Int) bool {
	return p.VerifyWithChallenge(pk, createChallenge(context, nonce1, p.ChallengeContribution(pk)))
}

// Verify verifies the proof against the given public key and the provided
// reconstruted challenge.
func (p *ProofD) VerifyWithChallenge(pk *PublicKey, reconstructedChallenge *big.Int) bool {
	return p.correctResponseSizes(pk) && p.c.Cmp(reconstructedChallenge) == 0
}

// ChallengeContribution returns the contribution of this proof to the
// challenge.
func (p *ProofD) ChallengeContribution(pk *PublicKey) []*big.Int {
	return []*big.Int{p.A, p.reconstructZ(pk)}
}

// SecretKeyResponse returns the secret key response (as part of Proof
// interface).
func (p *ProofD) SecretKeyResponse() *big.Int {
	return p.aResponses[0]
}

// Challenge returns the challenge in the proof (part of the Proof interface).
func (p *ProofD) Challenge() *big.Int {
	return p.c
}

// ProofBuilder is an interface for a prof builder. That is, an object to hold
// the state to build a list of bounded proofs (see ProofList).
type ProofBuilder interface {
	Commit(skRandomizer *big.Int) []*big.Int
	CreateProof(challenge *big.Int) Proof
}

// ProofList represents a list of (typically bounded) proofs.
type ProofList []Proof

var (
	// ErrMissingProofU is returned when a ProofU proof is missing in a prooflist
	// when this is expected.
	ErrMissingProofU = errors.New("Missing ProofU in ProofList, has a CredentialBuilder been added?")
)

// GetProofU returns the n'th ProofU in this proof list.
func (pl ProofList) GetProofU(n int) (*ProofU, error) {
	count := 0
	for _, proof := range pl {
		switch proof.(type) {
		case *ProofU:
			if count == n {
				return proof.(*ProofU), nil
			}
			count++
		}
	}
	return nil, ErrMissingProofU
}

// GetFirstProofU returns the first ProofU in this proof list
func (pl ProofList) GetFirstProofU() (*ProofU, error) {
	return pl.GetProofU(0)
}

// challengeContributions collects and returns all the challenge contributions
// of the proofs contained in the proof list.
func (pl ProofList) challengeContributions(publicKeys []*PublicKey, context, nonce *big.Int) []*big.Int {
	contributions := make([]*big.Int, 0, len(pl)*2)
	for i, proof := range pl {
		contributions = append(contributions, proof.ChallengeContribution(publicKeys[i])...)
	}
	return contributions
}

// Verify returns true when all the proofs inside verify and if shouldBeBound is
// set to true whether all proofs are properly bound.
func (pl ProofList) Verify(publicKeys []*PublicKey, context, nonce *big.Int, shouldBeBound bool) bool {
	if len(pl) == 0 {
		return true
	}

	if len(pl) != len(publicKeys) {
		return false
	}

	if shouldBeBound {
		contributions := pl.challengeContributions(publicKeys, context, nonce)
		expectedChallenge := createChallenge(context, nonce, contributions)
		expectedSecretKeyResponse := pl[0].SecretKeyResponse()
		for i, proof := range pl {
			if expectedSecretKeyResponse.Cmp(proof.SecretKeyResponse()) != 0 ||
				!proof.VerifyWithChallenge(publicKeys[i], expectedChallenge) {
				return false
			}
		}
	} else {
		for i, proof := range pl {
			// if !proof.Verify(publicKeys[i], context, nonce) {
			if !proof.VerifyWithChallenge(publicKeys[i], createChallenge(context, nonce, proof.ChallengeContribution(publicKeys[i]))) {
				return false
			}
		}
	}

	return true
}

// BuildProofList builds a list of bounded proofs. For this it is given a list
// of ProofBuilders. Examples of proof builders are Builder and
// DisclosureProofBuilder.
func BuildProofList(params *SystemParameters, context, nonce *big.Int, proofBuilders []ProofBuilder) ProofList {
	skCommitment, _ := randomBigInt(params.LmCommit)

	commitmentValues := make([]*big.Int, 0, len(proofBuilders)*2)
	for _, pb := range proofBuilders {
		commitmentValues = append(commitmentValues, pb.Commit(skCommitment)...)
	}

	// Create a shared challenge
	challenge := createChallenge(context, nonce, commitmentValues)

	proofs := make([]Proof, len(proofBuilders))
	// Now create proofs using this challenge
	for i, v := range proofBuilders {
		proofs[i] = v.CreateProof(challenge)
	}
	return proofs
}
<|endoftext|>


<commit_before>package storage

import (
	"fmt"
	"strings"

	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/lxd/storage/drivers"
	"github.com/lxc/lxd/shared/api"
	log "github.com/lxc/lxd/shared/log15"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/logging"
)

// MockBackend controls whether to run the storage logic in mock mode.
var MockBackend = false

// volIDFuncMake returns a function that can be supplied to the underlying storage drivers allowing
// them to lookup the volume ID for a specific volume type and volume name. This function is tied
// to the Pool ID that it is generated for, meaning the storage drivers do not need to know the ID
// of the pool they belong to, or do they need access to the database.
func volIDFuncMake(state *state.State, poolID int64) func(volType drivers.VolumeType, volName string) (int64, error) {
	// Return a function to retrieve a volume ID for a volume Name for use in driver.
	return func(volType drivers.VolumeType, volName string) (int64, error) {
		volTypeID, err := VolumeTypeToDBType(volType)
		if err != nil {
			return -1, err
		}

		// It is possible for the project name to be encoded into the volume name in the
		// format <project>_<volume>. However not all volume types currently use this
		// encoding format, so if there is no underscore in the volume name then we assume
		// the project is default.
		project := "default"
		if volType == drivers.VolumeTypeContainer || volType == drivers.VolumeTypeVM {
			volParts := strings.SplitN(volName, "_", 2)
			if len(volParts) > 1 {
				project = volParts[0]
				volName = volParts[1]
			}
		}

		volID, _, err := state.Cluster.StoragePoolNodeVolumeGetTypeByProject(project, volName, volTypeID, poolID)
		if err != nil {
			if err == db.ErrNoSuchObject {
				return -1, fmt.Errorf("Failed to get volume ID for project '%s', volume '%s', type '%s': Volume doesn't exist", project, volName, volType)
			}

			return -1, err
		}

		return volID, nil
	}
}

// CreatePool creates a new storage pool on disk and returns a Pool interface.
func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePool, op *operations.Operation) (Pool, error) {
	// Sanity checks.
	if dbPool == nil {
		return nil, ErrNilValue
	}

	// Ensure a config map exists.
	if dbPool.Config == nil {
		dbPool.Config = map[string]string{}
	}

	// Handle mock requests.
	if MockBackend {
		pool := mockBackend{}
		pool.name = dbPool.Name
		pool.state = state
		pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": "mock", "pool": pool.name})
		return &pool, nil
	}

	logger := logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": dbPool.Name})

	// Load the storage driver.
	driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules)
	if err != nil {
		return nil, err
	}

	// Setup the pool struct.
	pool := lxdBackend{}
	pool.driver = driver
	pool.id = poolID
	pool.name = dbPool.Name
	pool.state = state
	pool.logger = logger

	// Create the pool itself on the storage device..
	err = pool.create(dbPool, op)
	if err != nil {
		return nil, err
	}

	return &pool, nil
}

// GetPoolByName retrieves the pool from the database by its name and returns a Pool interface.
func GetPoolByName(state *state.State, name string) (Pool, error) {
	// Handle mock requests.
	if MockBackend {
		pool := mockBackend{}
		pool.name = name
		pool.state = state
		pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": "mock", "pool": pool.name})
		return &pool, nil
	}

	// Load the database record.
	poolID, dbPool, err := state.Cluster.StoragePoolGet(name)
	if err != nil {
		return nil, err
	}

	// Ensure a config map exists.
	if dbPool.Config == nil {
		dbPool.Config = map[string]string{}
	}

	logger := logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": dbPool.Name})

	// Load the storage driver.
	driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules)
	if err != nil {
		return nil, err
	}

	// Setup the pool struct.
	pool := lxdBackend{}
	pool.driver = driver
	pool.id = poolID
	pool.name = dbPool.Name
	pool.state = state
	pool.logger = logger

	return &pool, nil
}

// GetPoolByInstanceName retrieves the pool from the database using the instance's project and name.
func GetPoolByInstanceName(s *state.State, projectName, instanceName string) (Pool, error) {
	poolName, err := s.Cluster.ContainerPool(projectName, instanceName)
	if err != nil {
		return nil, err
	}

	return GetPoolByName(s, poolName)
}
<commit_msg>lxd/storage/load: Adds comments<commit_after>package storage

import (
	"fmt"
	"strings"

	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/lxd/storage/drivers"
	"github.com/lxc/lxd/shared/api"
	log "github.com/lxc/lxd/shared/log15"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/logging"
)

// MockBackend controls whether to run the storage logic in mock mode.
var MockBackend = false

// volIDFuncMake returns a function that can be supplied to the underlying storage drivers allowing
// them to lookup the volume ID for a specific volume type and volume name. This function is tied
// to the Pool ID that it is generated for, meaning the storage drivers do not need to know the ID
// of the pool they belong to, or do they need access to the database.
func volIDFuncMake(state *state.State, poolID int64) func(volType drivers.VolumeType, volName string) (int64, error) {
	// Return a function to retrieve a volume ID for a volume Name for use in driver.
	return func(volType drivers.VolumeType, volName string) (int64, error) {
		volTypeID, err := VolumeTypeToDBType(volType)
		if err != nil {
			return -1, err
		}

		// It is possible for the project name to be encoded into the volume name in the
		// format <project>_<volume>. However not all volume types currently use this
		// encoding format, so if there is no underscore in the volume name then we assume
		// the project is default.
		project := "default"

		// Currently only Containers and VMs support project level volumes.
		// This means that other volume types may have underscores in their names that don't
		// indicate the project name.
		if volType == drivers.VolumeTypeContainer || volType == drivers.VolumeTypeVM {
			volParts := strings.SplitN(volName, "_", 2)
			if len(volParts) > 1 {
				project = volParts[0]
				volName = volParts[1]
			}
		}

		volID, _, err := state.Cluster.StoragePoolNodeVolumeGetTypeByProject(project, volName, volTypeID, poolID)
		if err != nil {
			if err == db.ErrNoSuchObject {
				return -1, fmt.Errorf("Failed to get volume ID for project '%s', volume '%s', type '%s': Volume doesn't exist", project, volName, volType)
			}

			return -1, err
		}

		return volID, nil
	}
}

// CreatePool creates a new storage pool on disk and returns a Pool interface.
func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePool, op *operations.Operation) (Pool, error) {
	// Sanity checks.
	if dbPool == nil {
		return nil, ErrNilValue
	}

	// Ensure a config map exists.
	if dbPool.Config == nil {
		dbPool.Config = map[string]string{}
	}

	// Handle mock requests.
	if MockBackend {
		pool := mockBackend{}
		pool.name = dbPool.Name
		pool.state = state
		pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": "mock", "pool": pool.name})
		return &pool, nil
	}

	logger := logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": dbPool.Name})

	// Load the storage driver.
	driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules)
	if err != nil {
		return nil, err
	}

	// Setup the pool struct.
	pool := lxdBackend{}
	pool.driver = driver
	pool.id = poolID
	pool.name = dbPool.Name
	pool.state = state
	pool.logger = logger

	// Create the pool itself on the storage device..
	err = pool.create(dbPool, op)
	if err != nil {
		return nil, err
	}

	return &pool, nil
}

// GetPoolByName retrieves the pool from the database by its name and returns a Pool interface.
func GetPoolByName(state *state.State, name string) (Pool, error) {
	// Handle mock requests.
	if MockBackend {
		pool := mockBackend{}
		pool.name = name
		pool.state = state
		pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": "mock", "pool": pool.name})
		return &pool, nil
	}

	// Load the database record.
	poolID, dbPool, err := state.Cluster.StoragePoolGet(name)
	if err != nil {
		return nil, err
	}

	// Ensure a config map exists.
	if dbPool.Config == nil {
		dbPool.Config = map[string]string{}
	}

	logger := logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": dbPool.Name})

	// Load the storage driver.
	driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules)
	if err != nil {
		return nil, err
	}

	// Setup the pool struct.
	pool := lxdBackend{}
	pool.driver = driver
	pool.id = poolID
	pool.name = dbPool.Name
	pool.state = state
	pool.logger = logger

	return &pool, nil
}

// GetPoolByInstanceName retrieves the pool from the database using the instance's project and name.
func GetPoolByInstanceName(s *state.State, projectName, instanceName string) (Pool, error) {
	poolName, err := s.Cluster.ContainerPool(projectName, instanceName)
	if err != nil {
		return nil, err
	}

	return GetPoolByName(s, poolName)
}
<|endoftext|>