<commit_before>// Person struct with methods of value receiver

package main

import (
	"fmt"
	"time"
)

type Person struct {
	FirstName, LastName string
	Dob                 time.Time
	Email, Location     string
}

//A person method with pointer receiver
func (p Person) PrintName() {
	fmt.Printf("\n%s %s\n", p.FirstName, p.LastName)
}

//A person method with pointer receiver
func (p Person) PrintDetails() {
	fmt.Printf("[Date of Birth: %s, Email: %s, Location: %s ]\n", p.Dob.String(), p.Email, p.Location)
}

func main() {
	var p Person
	p.FirstName = "Rob"
	p.LastName = "Pike"
	p.Dob = time.Date(1957, time.February, 17, 0, 0, 0, 0, time.UTC)
	p.Email = "pike.email.com"
	p.Location = "California"

	p1 := Person{
		FirstName: "Shiju",
		LastName:  "Varghese",
		Dob:       time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
		Email:     "shiju@email.com",
		Location:  "Kochi",
	}
	p.PrintName()
	p.PrintDetails()
	p1.PrintName()
	p1.PrintDetails()

}
<commit_msg>minor changes<commit_after>// Person struct with methods of value receiver

package main

import (
	"fmt"
	"time"
)

type Person struct {
	FirstName, LastName string
	Dob                 time.Time
	Email, Location     string
}

//A person method with value receiver
func (p Person) PrintName() {
	fmt.Printf("\n%s %s\n", p.FirstName, p.LastName)
}

//A person method with value receiver
func (p Person) PrintDetails() {
	fmt.Printf("[Date of Birth: %s, Email: %s, Location: %s ]\n", p.Dob.String(), p.Email, p.Location)
}

func main() {
	var p Person
	p.FirstName = "Rob"
	p.LastName = "Pike"
	p.Dob = time.Date(1957, time.February, 17, 0, 0, 0, 0, time.UTC)
	p.Email = "pike@email.com"
	p.Location = "California"

	// Struct literal
	p1 := Person{
		FirstName: "Shiju",
		LastName:  "Varghese",
		Dob:       time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
		Email:     "shiju@email.com",
		Location:  "Kochi",
	}
	p.PrintName()
	p.PrintDetails()
	p1.PrintName()
	p1.PrintDetails()

}
<|endoftext|>


<commit_before>package spirit

import (
	"fmt"
	"runtime"
	"strconv"
	"sync"
	"time"

	"github.com/gogap/errors"
	"github.com/gogap/logs"
)

var (
	MESSAGE_CHAN_SIZE = 1000
)

type BaseComponent struct {
	name          string
	receivers     map[string][]MessageReceiver
	handlers      map[string]ComponentHandler
	inPortHandler map[string]ComponentHandler

	runtimeLocker sync.Mutex
	isBuilt       bool

	status ComponentStatus

	portChans     map[string]*PortChan
	stoppingChans map[string]chan bool
	stopedChans   map[string]chan bool

	senderFactory MessageSenderFactory
}

func NewBaseComponent(componentName string) Component {
	if componentName == "" {
		panic("component name could not be empty")
	}

	return &BaseComponent{
		name:          componentName,
		receivers:     make(map[string][]MessageReceiver),
		handlers:      make(map[string]ComponentHandler),
		inPortHandler: make(map[string]ComponentHandler),
		portChans:     make(map[string]*PortChan),
		stopedChans:   make(map[string]chan bool),
		stoppingChans: make(map[string]chan bool),
	}
}

func (p *BaseComponent) Name() string {
	return p.name
}

func (p *BaseComponent) SetMessageSenderFactory(factory MessageSenderFactory) Component {
	if factory == nil {
		panic(fmt.Sprintf("message sender factory could not be nil, component name: %s", p.name))
	}
	p.senderFactory = factory
	return p
}

func (p *BaseComponent) CallHandler(handlerName string, payload *Payload) (result interface{}, err error) {
	if handlerName == "" {
		err = ERR_HANDLER_NAME_IS_EMPTY.New(errors.Params{"name": p.name})
		return
	}

	if handler, exist := p.handlers[handlerName]; exist {
		if ret, e := handler(payload); e != nil {
			err = ERR_COMPONENT_HANDLER_RETURN_ERROR.New(errors.Params{"err": e})
			return
		} else {
			result = ret
			return
		}
	} else {
		err = ERR_COMPONENT_HANDLER_NOT_EXIST.New(errors.Params{"name": p.name, "handlerName": handlerName})
		return
	}
}

func (p *BaseComponent) RegisterHandler(name string, handler ComponentHandler) Component {
	if name == "" {
		panic(fmt.Sprintf("[component-%s] handle name could not be empty", p.name))
	}

	if handler == nil {
		panic(fmt.Sprintf("[component-%s] handler could not be nil, handler name: %s", p.name, name))
	}

	if _, exist := p.handlers[name]; exist {
		panic(fmt.Sprintf("[component-%s] handler of %s, already registered", p.name, name))
	} else {
		p.handlers[name] = handler
	}
	return p
}

func (p *BaseComponent) ListHandlers() (handlers map[string]ComponentHandler, err error) {
	handlers = make(map[string]ComponentHandler)
	for name, handler := range p.handlers {
		handlers[name] = handler
	}
	return
}

func (p *BaseComponent) GetHandlers(handlerNames ...string) (handlers map[string]ComponentHandler, err error) {
	if handlerNames == nil {
		return
	}

	ret := make(map[string]ComponentHandler)
	for _, name := range handlerNames {
		if h, exist := p.handlers[name]; !exist {
			err = ERR_COMPONENT_HANDLER_NOT_EXIST.New(errors.Params{"name": p.name, "handlerName": name})
			return
		} else {
			ret[name] = h
		}
	}
	handlers = ret
	return
}

func (p *BaseComponent) BindHandler(inPortName, handlerName string) Component {
	if inPortName == "" {
		panic(fmt.Sprintf("[component-%s] in port name could not be empty", p.name))
	}

	if handlerName == "" {
		panic(fmt.Sprintf("[component-%s] handler name could not be empty, in port name: %s", p.name, inPortName))
	}

	var handler ComponentHandler
	exist := false

	if handler, exist = p.handlers[handlerName]; !exist {
		panic(fmt.Sprintf("[component-%s] handler not exist, handler name: %s", p.name, handlerName))
	}

	if _, exist = p.inPortHandler[inPortName]; exist {
		panic(fmt.Sprintf("[component-%s] in port of %s, already have handler, handler name: %s", p.name, inPortName, handlerName))
	} else {
		p.inPortHandler[inPortName] = handler
	}

	return p
}

func (p *BaseComponent) GetReceivers(inPortName string) []MessageReceiver {
	if inPortName == "" {
		panic(fmt.Sprintf("[component-%s] in port name could not be empty", p.name))
	}

	receivers, _ := p.receivers[inPortName]
	return receivers
}

func (p *BaseComponent) BindReceiver(inPortName string, receivers ...MessageReceiver) Component {
	if inPortName == "" {
		panic(fmt.Sprintf("[component-%s] in port name could not be empty", p.name))
	}

	if receivers == nil || len(receivers) == 0 {
		panic(fmt.Sprintf("[component-%s] receivers could not be nil or 0 length, in port name: %s", p.name, inPortName))
	}

	inPortReceivers := map[MessageReceiver]bool{}

	for _, receiver := range receivers {
		if _, exist := inPortReceivers[receiver]; !exist {
			inPortReceivers[receiver] = true
		} else {
			panic(fmt.Sprintf("[component-%s] duplicate receiver type with in port, in port name: %s, receiver type: %s", p.name, inPortName, receiver.Type()))
		}
	}

	p.receivers[inPortName] = receivers

	return p
}

func (p *BaseComponent) Build() Component {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	if p.isBuilt {
		panic(fmt.Sprintf("the component of %s already built", p.name))
	}

	if p.senderFactory == nil {
		panic(fmt.Sprintf("the component of %s did not have sender factory", p.name))
	}

	for inPortName, _ := range p.receivers {
		portChan := new(PortChan)
		portChan.Error = make(chan error, MESSAGE_CHAN_SIZE)
		portChan.Message = make(chan ComponentMessage, MESSAGE_CHAN_SIZE)
		portChan.Signal = make(chan int)
		portChan.Stoped = make(chan bool)

		p.portChans[inPortName] = portChan
		p.stopedChans[inPortName] = make(chan bool)
		p.stoppingChans[inPortName] = make(chan bool)
	}

	p.isBuilt = true

	return p
}

func (p *BaseComponent) Run() {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	if !p.isBuilt {
		panic(fmt.Sprintf("the component of %s should be build first", p.name))
	}

	if p.status > 0 {
		panic(fmt.Sprintf("the component of %s already running", p.name))
	}

	for inPortName, typedReceivers := range p.receivers {
		var portChan *PortChan
		exist := false
		if portChan, exist = p.portChans[inPortName]; !exist {
			panic(fmt.Sprintf("port chan of component: %s, not exist", p.name))
		}

		for _, receiver := range typedReceivers {
			go receiver.Receive(portChan)
		}
	}

	p.status = STATUS_RUNNING

	p.ReceiverLoop()
	return
}

func (p *BaseComponent) ReceiverLoop() {
	loopInPortNames := []string{}
	for inPortName, _ := range p.receivers {
		loopInPortNames = append(loopInPortNames, inPortName)
	}

	for _, inPortName := range loopInPortNames {
		portChan := p.portChans[inPortName]
		stopedChan := p.stopedChans[inPortName]
		stoppingChan := p.stoppingChans[inPortName]
		go func(portName string, respChan chan ComponentMessage, errChan chan error, stoppingChan chan bool, stopedChan chan bool) {
			isStopping := false
			stoplogTime := time.Now()
			for {
				if isStopping {
					now := time.Now()

					if len(respChan) == 0 && len(errChan) == 0 {
						logs.Warn(fmt.Sprintf("* port - %s have no message, so it will be stop running", portName))
						stopedChan <- true
						return
					} else {
						if now.Sub(stoplogTime) >= time.Second {
							stoplogTime = now
							logs.Warn(fmt.Sprintf("* port - %s stopping, MsgLen: %d, ErrLen: %d", portName, len(respChan), len(errChan)))
						}
					}
				}

				select {
				case compMsg := <-respChan:
					{
						go p.handleComponentMessage(portName, compMsg)
					}
				case respErr := <-errChan:
					{
						logs.Error(respErr)
					}
				case isStopping = <-stoppingChan:
					{
						stoplogTime = time.Now()
						logs.Warn(fmt.Sprintf("* port - %s received stop signal", portName))
					}
				case <-time.After(time.Millisecond * 1):
					{
						if len(respChan) == 0 && isStopping {
							stopedChan <- true
							return
						}
					}
				}
			}
		}(inPortName, portChan.Message, portChan.Error, stoppingChan, stopedChan)
	}
}

func (p *BaseComponent) PauseOrResume() {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	if p.status == STATUS_RUNNING {
		for _, Chans := range p.portChans {
			select {
			case Chans.Signal <- SIG_PAUSE:
			case <-time.After(time.Second * 2):
			}
		}
		p.status = STATUS_PAUSED
	} else if p.status == STATUS_PAUSED {
		for _, Chans := range p.portChans {
			select {
			case Chans.Signal <- SIG_RESUME:
			case <-time.After(time.Second * 2):
			}
		}
		p.status = STATUS_RUNNING
	} else {
		logs.Warn("[base component] pause or resume at error status")
	}

}

func (p *BaseComponent) Stop() {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	//stop queues first
	logs.Warn("* begin stop port receivers")
	wgReceiverBeginStop := sync.WaitGroup{}
	for _, Chans := range p.portChans {
		wgReceiverBeginStop.Add(1)
		go func(stopedChan chan bool) {
			defer wgReceiverBeginStop.Done()
			select {
			case Chans.Signal <- SIG_STOP:
			case <-time.After(time.Second * 5):
			}
		}(Chans.Stoped)
	}
	wgReceiverBeginStop.Wait()

	logs.Warn("* waiting for port receivers stopped signal")

	wgReceiverStop := sync.WaitGroup{}
	for _, Chans := range p.portChans {
		wgReceiverStop.Add(1)
		go func(stopedChan chan bool) {
			defer wgReceiverStop.Done()
			select {
			case _ = <-stopedChan:
			case <-time.After(time.Second * 60):
			}
		}(Chans.Stoped)
	}
	wgReceiverStop.Wait()

	logs.Warn("* begin stop received response message handler")
	wgHandlerBeginStop := sync.WaitGroup{}
	for _, Chan := range p.stoppingChans {
		wgHandlerBeginStop.Add(1)
		go func(stopedChan chan bool) {
			defer wgHandlerBeginStop.Done()
			select {
			case Chan <- true:
			case <-time.After(time.Second * 60):
			}
		}(Chan)
	}
	wgHandlerBeginStop.Wait()

	logs.Warn("* waiting for received response message handler stopped signal")
	wgHandlerStop := sync.WaitGroup{}
	for inportName, Chan := range p.stopedChans {
		wgHandlerStop.Add(1)
		go func(stopedChan chan bool, name string) {
			defer wgHandlerStop.Done()
			select {
			case _ = <-stopedChan:
				{
					logs.Warn("* component", name, "stoped")
				}
			case <-time.After(time.Second * 60):
			}
		}(Chan, inportName)
	}
	wgHandlerStop.Wait()

	p.status = STATUS_STOPED
}

func (p *BaseComponent) Status() ComponentStatus {
	return p.status
}

func (p *BaseComponent) callHandlerWithRecover(handler ComponentHandler, payload *Payload) (content interface{}, err error) {
	defer func() {
		if r := recover(); r != nil {
			buf := make([]byte, 1024)
			runtime.Stack(buf, false)
			err = ERR_COMPONENT_HANDLER_PANIC.New(errors.Params{"name": p.name, "err": string(buf)})
		}
	}()

	return handler(payload)
}

func (p *BaseComponent) handleComponentMessage(inPortName string, message ComponentMessage) {
	var handler ComponentHandler
	var err error
	var exist bool

	if message.graph == nil {
		logs.Error(ERR_MESSAGE_GRAPH_IS_NIL.New())
		return
	}

	if handler, exist = p.inPortHandler[inPortName]; !exist {
		panic(fmt.Sprintf("in port of %s not exist", inPortName))
	}

	var address MessageAddress
	var nextGraphIndex int32 = 0
	var content interface{}

	if content, err = p.callHandlerWithRecover(handler, &message.payload); err != nil {
		if !errors.IsErrCode(err) {
			err = ERR_COMPONENT_HANDLER_RETURN_ERROR.New(errors.Params{"err": err, "name": p.name, "port": inPortName})
		}

		logs.Error(err)

		if address, exist = message.graph[ERROR_MSG_ADDR]; exist {
			errCode := err.(errors.ErrCode)
			message.payload.err.AddressId = message.currentGraphIndex
			message.payload.err.Id = errCode.Id()
			message.payload.err.Namespace = errCode.Namespace()
			message.payload.err.Code = errCode.Code()
			message.payload.err.Message = errCode.Error()

			nextGraphIndex = ERROR_MSG_ADDR_INT //forword to the error port
		} else {
			return
		}
	} else {
		message.payload.SetContent(content)
		if address, exist = message.graph[strconv.Itoa(int(message.currentGraphIndex)+1)]; exist {
			nextGraphIndex = message.currentGraphIndex + 1 //forword the next component
		} else {
			return
		}
	}

	message.currentGraphIndex = nextGraphIndex

	go func(addrType, url string, msg ComponentMessage) {
		var sender MessageSender
		if sender, err = p.senderFactory.NewSender(addrType); err != nil {
			logs.Error(err)
			return
		}

		if err = sender.Send(url, msg); err != nil {
			logs.Error(err)
			return
		}
	}(address.Type, address.Url, message)

	return
}
<commit_msg>fix stop go routine issue<commit_after>package spirit

import (
	"fmt"
	"runtime"
	"strconv"
	"sync"
	"time"

	"github.com/gogap/errors"
	"github.com/gogap/logs"
)

var (
	MESSAGE_CHAN_SIZE = 1000
)

type BaseComponent struct {
	name          string
	receivers     map[string][]MessageReceiver
	handlers      map[string]ComponentHandler
	inPortHandler map[string]ComponentHandler

	runtimeLocker sync.Mutex
	isBuilt       bool

	status ComponentStatus

	portChans     map[string]*PortChan
	stoppingChans map[string]chan bool
	stopedChans   map[string]chan bool

	senderFactory MessageSenderFactory
}

func NewBaseComponent(componentName string) Component {
	if componentName == "" {
		panic("component name could not be empty")
	}

	return &BaseComponent{
		name:          componentName,
		receivers:     make(map[string][]MessageReceiver),
		handlers:      make(map[string]ComponentHandler),
		inPortHandler: make(map[string]ComponentHandler),
		portChans:     make(map[string]*PortChan),
		stopedChans:   make(map[string]chan bool),
		stoppingChans: make(map[string]chan bool),
	}
}

func (p *BaseComponent) Name() string {
	return p.name
}

func (p *BaseComponent) SetMessageSenderFactory(factory MessageSenderFactory) Component {
	if factory == nil {
		panic(fmt.Sprintf("message sender factory could not be nil, component name: %s", p.name))
	}
	p.senderFactory = factory
	return p
}

func (p *BaseComponent) CallHandler(handlerName string, payload *Payload) (result interface{}, err error) {
	if handlerName == "" {
		err = ERR_HANDLER_NAME_IS_EMPTY.New(errors.Params{"name": p.name})
		return
	}

	if handler, exist := p.handlers[handlerName]; exist {
		if ret, e := handler(payload); e != nil {
			err = ERR_COMPONENT_HANDLER_RETURN_ERROR.New(errors.Params{"err": e})
			return
		} else {
			result = ret
			return
		}
	} else {
		err = ERR_COMPONENT_HANDLER_NOT_EXIST.New(errors.Params{"name": p.name, "handlerName": handlerName})
		return
	}
}

func (p *BaseComponent) RegisterHandler(name string, handler ComponentHandler) Component {
	if name == "" {
		panic(fmt.Sprintf("[component-%s] handle name could not be empty", p.name))
	}

	if handler == nil {
		panic(fmt.Sprintf("[component-%s] handler could not be nil, handler name: %s", p.name, name))
	}

	if _, exist := p.handlers[name]; exist {
		panic(fmt.Sprintf("[component-%s] handler of %s, already registered", p.name, name))
	} else {
		p.handlers[name] = handler
	}
	return p
}

func (p *BaseComponent) ListHandlers() (handlers map[string]ComponentHandler, err error) {
	handlers = make(map[string]ComponentHandler)
	for name, handler := range p.handlers {
		handlers[name] = handler
	}
	return
}

func (p *BaseComponent) GetHandlers(handlerNames ...string) (handlers map[string]ComponentHandler, err error) {
	if handlerNames == nil {
		return
	}

	ret := make(map[string]ComponentHandler)
	for _, name := range handlerNames {
		if h, exist := p.handlers[name]; !exist {
			err = ERR_COMPONENT_HANDLER_NOT_EXIST.New(errors.Params{"name": p.name, "handlerName": name})
			return
		} else {
			ret[name] = h
		}
	}
	handlers = ret
	return
}

func (p *BaseComponent) BindHandler(inPortName, handlerName string) Component {
	if inPortName == "" {
		panic(fmt.Sprintf("[component-%s] in port name could not be empty", p.name))
	}

	if handlerName == "" {
		panic(fmt.Sprintf("[component-%s] handler name could not be empty, in port name: %s", p.name, inPortName))
	}

	var handler ComponentHandler
	exist := false

	if handler, exist = p.handlers[handlerName]; !exist {
		panic(fmt.Sprintf("[component-%s] handler not exist, handler name: %s", p.name, handlerName))
	}

	if _, exist = p.inPortHandler[inPortName]; exist {
		panic(fmt.Sprintf("[component-%s] in port of %s, already have handler, handler name: %s", p.name, inPortName, handlerName))
	} else {
		p.inPortHandler[inPortName] = handler
	}

	return p
}

func (p *BaseComponent) GetReceivers(inPortName string) []MessageReceiver {
	if inPortName == "" {
		panic(fmt.Sprintf("[component-%s] in port name could not be empty", p.name))
	}

	receivers, _ := p.receivers[inPortName]
	return receivers
}

func (p *BaseComponent) BindReceiver(inPortName string, receivers ...MessageReceiver) Component {
	if inPortName == "" {
		panic(fmt.Sprintf("[component-%s] in port name could not be empty", p.name))
	}

	if receivers == nil || len(receivers) == 0 {
		panic(fmt.Sprintf("[component-%s] receivers could not be nil or 0 length, in port name: %s", p.name, inPortName))
	}

	inPortReceivers := map[MessageReceiver]bool{}

	for _, receiver := range receivers {
		if _, exist := inPortReceivers[receiver]; !exist {
			inPortReceivers[receiver] = true
		} else {
			panic(fmt.Sprintf("[component-%s] duplicate receiver type with in port, in port name: %s, receiver type: %s", p.name, inPortName, receiver.Type()))
		}
	}

	p.receivers[inPortName] = receivers

	return p
}

func (p *BaseComponent) Build() Component {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	if p.isBuilt {
		panic(fmt.Sprintf("the component of %s already built", p.name))
	}

	if p.senderFactory == nil {
		panic(fmt.Sprintf("the component of %s did not have sender factory", p.name))
	}

	for inPortName, _ := range p.receivers {
		portChan := new(PortChan)
		portChan.Error = make(chan error, MESSAGE_CHAN_SIZE)
		portChan.Message = make(chan ComponentMessage, MESSAGE_CHAN_SIZE)
		portChan.Signal = make(chan int)
		portChan.Stoped = make(chan bool)

		p.portChans[inPortName] = portChan
		p.stopedChans[inPortName] = make(chan bool)
		p.stoppingChans[inPortName] = make(chan bool)
	}

	p.isBuilt = true

	return p
}

func (p *BaseComponent) Run() {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	if !p.isBuilt {
		panic(fmt.Sprintf("the component of %s should be build first", p.name))
	}

	if p.status > 0 {
		panic(fmt.Sprintf("the component of %s already running", p.name))
	}

	for inPortName, typedReceivers := range p.receivers {
		var portChan *PortChan
		exist := false
		if portChan, exist = p.portChans[inPortName]; !exist {
			panic(fmt.Sprintf("port chan of component: %s, not exist", p.name))
		}

		for _, receiver := range typedReceivers {
			go receiver.Receive(portChan)
		}
	}

	p.status = STATUS_RUNNING

	p.ReceiverLoop()
	return
}

func (p *BaseComponent) ReceiverLoop() {
	loopInPortNames := []string{}
	for inPortName, _ := range p.receivers {
		loopInPortNames = append(loopInPortNames, inPortName)
	}

	for _, inPortName := range loopInPortNames {
		portChan := p.portChans[inPortName]
		stopedChan := p.stopedChans[inPortName]
		stoppingChan := p.stoppingChans[inPortName]
		go func(portName string, respChan chan ComponentMessage, errChan chan error, stoppingChan chan bool, stopedChan chan bool) {
			isStopping := false
			stoplogTime := time.Now()
			for {
				if isStopping {
					now := time.Now()

					if len(respChan) == 0 && len(errChan) == 0 {
						logs.Warn(fmt.Sprintf("* port - %s have no message, so it will be stop running", portName))
						stopedChan <- true
						return
					} else {
						if now.Sub(stoplogTime) >= time.Second {
							stoplogTime = now
							logs.Warn(fmt.Sprintf("* port - %s stopping, MsgLen: %d, ErrLen: %d", portName, len(respChan), len(errChan)))
						}
					}
				}

				select {
				case compMsg := <-respChan:
					{
						go p.handleComponentMessage(portName, compMsg)
					}
				case respErr := <-errChan:
					{
						logs.Error(respErr)
					}
				case isStopping = <-stoppingChan:
					{
						stoplogTime = time.Now()
						logs.Warn(fmt.Sprintf("* port - %s received stop signal", portName))
					}
				case <-time.After(time.Millisecond * 1):
					{
						if len(respChan) == 0 && isStopping {
							stopedChan <- true
							return
						}
					}
				}
			}
		}(inPortName, portChan.Message, portChan.Error, stoppingChan, stopedChan)
	}
}

func (p *BaseComponent) PauseOrResume() {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	if p.status == STATUS_RUNNING {
		for _, Chans := range p.portChans {
			select {
			case Chans.Signal <- SIG_PAUSE:
			case <-time.After(time.Second * 2):
			}
		}
		p.status = STATUS_PAUSED
	} else if p.status == STATUS_PAUSED {
		for _, Chans := range p.portChans {
			select {
			case Chans.Signal <- SIG_RESUME:
			case <-time.After(time.Second * 2):
			}
		}
		p.status = STATUS_RUNNING
	} else {
		logs.Warn("[base component] pause or resume at error status")
	}

}

func (p *BaseComponent) Stop() {
	p.runtimeLocker.Lock()
	defer p.runtimeLocker.Unlock()

	//stop queues first
	logs.Warn("* begin stop port receivers")
	wgReceiverBeginStop := sync.WaitGroup{}
	for _, Chans := range p.portChans {
		wgReceiverBeginStop.Add(1)
		go func(singalChan chan int) {
			defer wgReceiverBeginStop.Done()
			select {
			case singalChan <- SIG_STOP:
			case <-time.After(time.Second * 5):
			}
		}(Chans.Signal)
	}
	wgReceiverBeginStop.Wait()

	logs.Warn("* waiting for port receivers stopped signal")

	wgReceiverStop := sync.WaitGroup{}
	for _, Chans := range p.portChans {
		wgReceiverStop.Add(1)
		go func(stopedChan chan bool) {
			defer wgReceiverStop.Done()
			select {
			case _ = <-stopedChan:
			case <-time.After(time.Second * 60):
			}
		}(Chans.Stoped)
	}
	wgReceiverStop.Wait()

	logs.Warn("* begin stop received response message handler")
	wgHandlerBeginStop := sync.WaitGroup{}
	for inportName, Chan := range p.stoppingChans {
		wgHandlerBeginStop.Add(1)
		go func(stopedChan chan bool, name string) {
			defer wgHandlerBeginStop.Done()
			select {
			case stopedChan <- true:
				{
					logs.Warn("* component begin stop port:", name)
				}
			case <-time.After(time.Second * 60):
			}
		}(Chan, inportName)
	}
	wgHandlerBeginStop.Wait()

	logs.Warn("* waiting for received response message handler stopped signal")
	wgHandlerStop := sync.WaitGroup{}
	for inportName, Chan := range p.stopedChans {
		wgHandlerStop.Add(1)
		go func(stopedChan chan bool, name string) {
			defer wgHandlerStop.Done()
			select {
			case _ = <-stopedChan:
				{
					logs.Warn("* component", name, "stoped")
				}
			case <-time.After(time.Second * 60):
			}
		}(Chan, inportName)
	}
	wgHandlerStop.Wait()

	p.status = STATUS_STOPED
}

func (p *BaseComponent) Status() ComponentStatus {
	return p.status
}

func (p *BaseComponent) callHandlerWithRecover(handler ComponentHandler, payload *Payload) (content interface{}, err error) {
	defer func() {
		if r := recover(); r != nil {
			buf := make([]byte, 1024)
			runtime.Stack(buf, false)
			err = ERR_COMPONENT_HANDLER_PANIC.New(errors.Params{"name": p.name, "err": string(buf)})
		}
	}()

	return handler(payload)
}

func (p *BaseComponent) handleComponentMessage(inPortName string, message ComponentMessage) {
	var handler ComponentHandler
	var err error
	var exist bool

	if message.graph == nil {
		logs.Error(ERR_MESSAGE_GRAPH_IS_NIL.New())
		return
	}

	if handler, exist = p.inPortHandler[inPortName]; !exist {
		panic(fmt.Sprintf("in port of %s not exist", inPortName))
	}

	var address MessageAddress
	var nextGraphIndex int32 = 0
	var content interface{}

	if content, err = p.callHandlerWithRecover(handler, &message.payload); err != nil {
		if !errors.IsErrCode(err) {
			err = ERR_COMPONENT_HANDLER_RETURN_ERROR.New(errors.Params{"err": err, "name": p.name, "port": inPortName})
		}

		logs.Error(err)

		if address, exist = message.graph[ERROR_MSG_ADDR]; exist {
			errCode := err.(errors.ErrCode)
			message.payload.err.AddressId = message.currentGraphIndex
			message.payload.err.Id = errCode.Id()
			message.payload.err.Namespace = errCode.Namespace()
			message.payload.err.Code = errCode.Code()
			message.payload.err.Message = errCode.Error()

			nextGraphIndex = ERROR_MSG_ADDR_INT //forword to the error port
		} else {
			return
		}
	} else {
		message.payload.SetContent(content)
		if address, exist = message.graph[strconv.Itoa(int(message.currentGraphIndex)+1)]; exist {
			nextGraphIndex = message.currentGraphIndex + 1 //forword the next component
		} else {
			return
		}
	}

	message.currentGraphIndex = nextGraphIndex

	go func(addrType, url string, msg ComponentMessage) {
		var sender MessageSender
		if sender, err = p.senderFactory.NewSender(addrType); err != nil {
			logs.Error(err)
			return
		}

		if err = sender.Send(url, msg); err != nil {
			logs.Error(err)
			return
		}
	}(address.Type, address.Url, message)

	return
}
<|endoftext|>


<commit_before>package usbid

// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import (
	"fmt"
	"strconv"
)

// ID represents a vendor or product ID.
type ID uint16

// String returns a hexadecimal ID.
func (id ID) String() string {
	return fmt.Sprintf("%04x", int(id))
}

// ClassCode represents a USB-IF (Implementers Forum) class or subclass code.
type ClassCode uint8

// Standard classes defined by USB spec, see https://www.usb.org/defined-class-codes
const (
	ClassPerInterface       ClassCode = 0x00
	ClassAudio              ClassCode = 0x01
	ClassComm               ClassCode = 0x02
	ClassHID                ClassCode = 0x03
	ClassPhysical           ClassCode = 0x05
	ClassImage              ClassCode = 0x06
	ClassPTP                ClassCode = ClassImage // legacy name for image
	ClassPrinter            ClassCode = 0x07
	ClassMassStorage        ClassCode = 0x08
	ClassHub                ClassCode = 0x09
	ClassData               ClassCode = 0x0a
	ClassSmartCard          ClassCode = 0x0b
	ClassContentSecurity    ClassCode = 0x0d
	ClassVideo              ClassCode = 0x0e
	ClassPersonalHealthcare ClassCode = 0x0f
	ClassAudioVideo         ClassCode = 0x10
	ClassBillboard          ClassCode = 0x11
	ClassUSBTypeCBridge     ClassCode = 0x12
	ClassDiagnosticDevice   ClassCode = 0xdc
	ClassWireless           ClassCode = 0xe0
	ClassMiscellaneous      ClassCode = 0xef
	ClassApplication        ClassCode = 0xfe
	ClassVendorSpec         ClassCode = 0xff
)

var classDescription = map[ClassCode]string{
	ClassPerInterface:       "per-interface",
	ClassAudio:              "audio",
	ClassComm:               "communications",
	ClassHID:                "human interface device",
	ClassPhysical:           "physical",
	ClassImage:              "image",
	ClassPrinter:            "printer",
	ClassMassStorage:        "mass storage",
	ClassHub:                "hub",
	ClassData:               "data",
	ClassSmartCard:          "smart card",
	ClassContentSecurity:    "content security",
	ClassVideo:              "video",
	ClassPersonalHealthcare: "personal healthcare",
	ClassAudioVideo:         "audio/video",
	ClassBillboard:          "billboard",
	ClassUSBTypeCBridge:     "USB type-C bridge",
	ClassDiagnosticDevice:   "diagnostic device",
	ClassWireless:           "wireless",
	ClassMiscellaneous:      "miscellaneous",
	ClassApplication:        "application-specific",
	ClassVendorSpec:         "vendor-specific",
}

func (c ClassCode) String() string {
	if d, ok := classDescription[c]; ok {
		return d
	}

	return strconv.Itoa(int(c))
}

// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8

func (p Protocol) String() string {
	return strconv.Itoa(int(p))
}
<commit_msg>shared/usbid: Removes all one-line assign and check statements.<commit_after>package usbid

// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import (
	"fmt"
	"strconv"
)

// ID represents a vendor or product ID.
type ID uint16

// String returns a hexadecimal ID.
func (id ID) String() string {
	return fmt.Sprintf("%04x", int(id))
}

// ClassCode represents a USB-IF (Implementers Forum) class or subclass code.
type ClassCode uint8

// Standard classes defined by USB spec, see https://www.usb.org/defined-class-codes
const (
	ClassPerInterface       ClassCode = 0x00
	ClassAudio              ClassCode = 0x01
	ClassComm               ClassCode = 0x02
	ClassHID                ClassCode = 0x03
	ClassPhysical           ClassCode = 0x05
	ClassImage              ClassCode = 0x06
	ClassPTP                ClassCode = ClassImage // legacy name for image
	ClassPrinter            ClassCode = 0x07
	ClassMassStorage        ClassCode = 0x08
	ClassHub                ClassCode = 0x09
	ClassData               ClassCode = 0x0a
	ClassSmartCard          ClassCode = 0x0b
	ClassContentSecurity    ClassCode = 0x0d
	ClassVideo              ClassCode = 0x0e
	ClassPersonalHealthcare ClassCode = 0x0f
	ClassAudioVideo         ClassCode = 0x10
	ClassBillboard          ClassCode = 0x11
	ClassUSBTypeCBridge     ClassCode = 0x12
	ClassDiagnosticDevice   ClassCode = 0xdc
	ClassWireless           ClassCode = 0xe0
	ClassMiscellaneous      ClassCode = 0xef
	ClassApplication        ClassCode = 0xfe
	ClassVendorSpec         ClassCode = 0xff
)

var classDescription = map[ClassCode]string{
	ClassPerInterface:       "per-interface",
	ClassAudio:              "audio",
	ClassComm:               "communications",
	ClassHID:                "human interface device",
	ClassPhysical:           "physical",
	ClassImage:              "image",
	ClassPrinter:            "printer",
	ClassMassStorage:        "mass storage",
	ClassHub:                "hub",
	ClassData:               "data",
	ClassSmartCard:          "smart card",
	ClassContentSecurity:    "content security",
	ClassVideo:              "video",
	ClassPersonalHealthcare: "personal healthcare",
	ClassAudioVideo:         "audio/video",
	ClassBillboard:          "billboard",
	ClassUSBTypeCBridge:     "USB type-C bridge",
	ClassDiagnosticDevice:   "diagnostic device",
	ClassWireless:           "wireless",
	ClassMiscellaneous:      "miscellaneous",
	ClassApplication:        "application-specific",
	ClassVendorSpec:         "vendor-specific",
}

func (c ClassCode) String() string {
	d, ok := classDescription[c]
	if ok {
		return d
	}

	return strconv.Itoa(int(c))
}

// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8

func (p Protocol) String() string {
	return strconv.Itoa(int(p))
}
<|endoftext|>


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

// The postpone package provides an io.ReadSeeker wrapper, and various functions
// which handle readers with different postponements such as open on read and
// preload to RAM
package postpone

import (
	"bytes"
	"github.com/joshlf13/errlist"
	"io"
	"fmt"
	"io/ioutil"
	"os"
)

type postpone struct {
	r      io.Reader
	rs     io.ReadSeeker
	getr   func() (io.Reader, error)
	getrs  func() (io.ReadSeeker, error)
	err    error
	loaded bool
	bad    bool
}

// NewFile takes a filepath, and returns an io.ReadSeeker.
// This ReadSeeker will wait to open the file until the
// first call to either Read or Seek.
func NewFile(file string) io.ReadSeeker {
	return NewFunc(func() (io.ReadSeeker, error) {
		f, err := os.Open(file)
		if err != nil {
			return nil, err
		}
		return f, nil
	})
}

// NewFilePre takes a filepath, and returns an io.ReadSeeker.
// This ReadSeeker will wait to open the file until the
// first call to either Read or Seek. Upon this first call,
// the entire contents of file, or as much as is available,
// will be read into an internal buffer, and the file
// will be closed.
func NewFilePre(file string) io.ReadSeeker {
	return NewFuncPre(func() (io.Reader, error) {
		f, err := os.Open(file)
		if err != nil {
			return nil, err
		}
		return f, nil
	})
}

// NewFunc takes a function which returns an io.ReadSeeker.
// This is so the given resource doesn't have to be
// opened until it is needed. Upon the first loaded
// or Seek call, r is called, the resultant loadedSeeker
// is stored, and r is discarded.
func NewFunc(r func() (io.ReadSeeker, error)) io.ReadSeeker {
	return &postpone{nil, nil, nil, r, nil, false, false}
}

// NewFuncPre is identical to NewFunc except it takes
// a reader rather than a loadedSeeker, and upon the first
// loaded or Seek call, it not only retreives the reader,
// it also preloads all of the data from the reader into
// an internal buffer, and discards the reader.
func NewFuncPre(r func() (io.Reader, error)) io.ReadSeeker {
	return &postpone{nil, nil, r, nil, nil, false, false}
}

// NewReader takes an io.Reader and, upon the first
// call to loaded or Seek, preloads all available data
// into an internal buffer, and discards the reader
func NewReader(r io.Reader) io.ReadSeeker {
	return &postpone{r, nil, nil, nil, nil, false, false}
}

func (p *postpone) Read(buf []byte) (int, error) {
	if !p.loaded {
		p.retreive()
	}
	if p.bad {
		return 0, p.err
	}
	i, err := p.rs.Read(buf)
	err = errlist.NewError(err).AddError(p.err).Err()
	fmt.Println(err == io.EOF)
	return i, errlist.NewError(err).AddError(p.err).Err()
}

func (p *postpone) Seek(offset int64, whence int) (int64, error) {
	if !p.loaded {
		p.retreive()
	}
	if p.bad {
		return 0, p.err
	}
	i, err := p.rs.Seek(offset, whence)
	return i, errlist.NewError(err).AddError(p.err).Err()
}

func (p *postpone) retreive() {
	if p.getr != nil {
		var r io.Reader
		r, p.err = p.getr()
		p.getr = nil
		if r == nil || p.err != nil {
			p.bad = true
		} else {
			buf, err := ioutil.ReadAll(r)
			p.err = err
			p.rs = bytes.NewReader(buf)
		}
	} else if p.getrs != nil {
		p.rs, p.err = p.getrs()
		p.getrs = nil
		if p.rs == nil {
			p.bad = true
		}
	} else {
		var buf []byte
		if p.r == nil {
			p.bad = true
		} else {
			buf, p.err = ioutil.ReadAll(p.r)
			p.rs = bytes.NewReader(buf)
		}
	}
	p.loaded = true
}
<commit_msg>Debugging commit - temporary<commit_after>// Copyright 2012 The Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The postpone package provides an io.ReadSeeker wrapper, and various functions
// which handle readers with different postponements such as open on read and
// preload to RAM
package postpone

import (
	"bytes"
	"github.com/joshlf13/errlist"
	"io"
	"fmt"
	"io/ioutil"
	"os"
)

type postpone struct {
	r      io.Reader
	rs     io.ReadSeeker
	getr   func() (io.Reader, error)
	getrs  func() (io.ReadSeeker, error)
	err    error
	loaded bool
	bad    bool
}

// NewFile takes a filepath, and returns an io.ReadSeeker.
// This ReadSeeker will wait to open the file until the
// first call to either Read or Seek.
func NewFile(file string) io.ReadSeeker {
	return NewFunc(func() (io.ReadSeeker, error) {
		f, err := os.Open(file)
		if err != nil {
			return nil, err
		}
		return f, nil
	})
}

// NewFilePre takes a filepath, and returns an io.ReadSeeker.
// This ReadSeeker will wait to open the file until the
// first call to either Read or Seek. Upon this first call,
// the entire contents of file, or as much as is available,
// will be read into an internal buffer, and the file
// will be closed.
func NewFilePre(file string) io.ReadSeeker {
	return NewFuncPre(func() (io.Reader, error) {
		f, err := os.Open(file)
		if err != nil {
			return nil, err
		}
		return f, nil
	})
}

// NewFunc takes a function which returns an io.ReadSeeker.
// This is so the given resource doesn't have to be
// opened until it is needed. Upon the first loaded
// or Seek call, r is called, the resultant loadedSeeker
// is stored, and r is discarded.
func NewFunc(r func() (io.ReadSeeker, error)) io.ReadSeeker {
	return &postpone{nil, nil, nil, r, nil, false, false}
}

// NewFuncPre is identical to NewFunc except it takes
// a reader rather than a loadedSeeker, and upon the first
// loaded or Seek call, it not only retreives the reader,
// it also preloads all of the data from the reader into
// an internal buffer, and discards the reader.
func NewFuncPre(r func() (io.Reader, error)) io.ReadSeeker {
	return &postpone{nil, nil, r, nil, nil, false, false}
}

// NewReader takes an io.Reader and, upon the first
// call to loaded or Seek, preloads all available data
// into an internal buffer, and discards the reader
func NewReader(r io.Reader) io.ReadSeeker {
	return &postpone{r, nil, nil, nil, nil, false, false}
}

func (p *postpone) Read(buf []byte) (int, error) {
	if !p.loaded {
		p.retreive()
	}
	if p.bad {
		return 0, p.err
	}
	i, err := p.rs.Read(buf)
	fmt.Println(err == io.EOF)
	err = errlist.NewError(err).AddError(p.err).Err()
	fmt.Println(err == io.EOF)
	return i, errlist.NewError(err).AddError(p.err).Err()
}

func (p *postpone) Seek(offset int64, whence int) (int64, error) {
	if !p.loaded {
		p.retreive()
	}
	if p.bad {
		return 0, p.err
	}
	i, err := p.rs.Seek(offset, whence)
	return i, errlist.NewError(err).AddError(p.err).Err()
}

func (p *postpone) retreive() {
	if p.getr != nil {
		var r io.Reader
		r, p.err = p.getr()
		p.getr = nil
		if r == nil || p.err != nil {
			p.bad = true
		} else {
			buf, err := ioutil.ReadAll(r)
			p.err = err
			p.rs = bytes.NewReader(buf)
		}
	} else if p.getrs != nil {
		p.rs, p.err = p.getrs()
		p.getrs = nil
		if p.rs == nil {
			p.bad = true
		}
	} else {
		var buf []byte
		if p.r == nil {
			p.bad = true
		} else {
			buf, p.err = ioutil.ReadAll(p.r)
			p.rs = bytes.NewReader(buf)
		}
	}
	p.loaded = true
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The gocql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//This file will be the future home for more policies
package gocql

import (
	"log"
	"sync"
	"sync/atomic"

	"github.com/hailocab/go-hostpool"
)

// RetryableQuery is an interface that represents a query or batch statement that
// exposes the correct functions for the retry policy logic to evaluate correctly.
type RetryableQuery interface {
	Attempts() int
	GetConsistency() Consistency
}

// RetryPolicy interface is used by gocql to determine if a query can be attempted
// again after a retryable error has been received. The interface allows gocql
// users to implement their own logic to determine if a query can be attempted
// again.
//
// See SimpleRetryPolicy as an example of implementing and using a RetryPolicy
// interface.
type RetryPolicy interface {
	Attempt(RetryableQuery) bool
}

// SimpleRetryPolicy has simple logic for attempting a query a fixed number of times.
//
// See below for examples of usage:
//
//     //Assign to the cluster
//     cluster.RetryPolicy = &gocql.SimpleRetryPolicy{NumRetries: 3}
//
//     //Assign to a query
//     query.RetryPolicy(&gocql.SimpleRetryPolicy{NumRetries: 1})
//
type SimpleRetryPolicy struct {
	NumRetries int //Number of times to retry a query
}

// Attempt tells gocql to attempt the query again based on query.Attempts being less
// than the NumRetries defined in the policy.
func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool {
	return q.Attempts() <= s.NumRetries
}

// HostSelectionPolicy is an interface for selecting
// the most appropriate host to execute a given query.
type HostSelectionPolicy interface {
	SetHosts
	SetPartitioner
	//Pick returns an iteration function over selected hosts
	Pick(*Query) NextHost
}

// SelectedHost is an interface returned when picking a host from a host
// selection policy.
type SelectedHost interface {
	Info() *HostInfo
	Mark(error)
}

// NextHost is an iteration function over picked hosts
type NextHost func() SelectedHost

// RoundRobinHostPolicy is a round-robin load balancing policy, where each host
// is tried sequentially for each query.
func RoundRobinHostPolicy() HostSelectionPolicy {
	return &roundRobinHostPolicy{hosts: []HostInfo{}}
}

type roundRobinHostPolicy struct {
	hosts []HostInfo
	pos   uint32
	mu    sync.RWMutex
}

func (r *roundRobinHostPolicy) SetHosts(hosts []HostInfo) {
	r.mu.Lock()
	r.hosts = hosts
	r.mu.Unlock()
}

func (r *roundRobinHostPolicy) SetPartitioner(partitioner string) {
	// noop
}

func (r *roundRobinHostPolicy) Pick(qry *Query) NextHost {
	// i is used to limit the number of attempts to find a host
	// to the number of hosts known to this policy
	var i uint32 = 0
	return func() SelectedHost {
		r.mu.RLock()
		if len(r.hosts) == 0 {
			r.mu.RUnlock()
			return nil
		}

		var host *HostInfo
		// always increment pos to evenly distribute traffic in case of
		// failures
		pos := atomic.AddUint32(&r.pos, 1)
		if int(i) < len(r.hosts) {
			host = &r.hosts[(pos)%uint32(len(r.hosts))]
			i++
		}
		r.mu.RUnlock()
		return selectedRoundRobinHost{host}
	}
}

// selectedRoundRobinHost is a host returned by the roundRobinHostPolicy and
// implements the SelectedHost interface
type selectedRoundRobinHost struct {
	info *HostInfo
}

func (host selectedRoundRobinHost) Info() *HostInfo {
	return host.info
}

func (host selectedRoundRobinHost) Mark(err error) {
	// noop
}

// TokenAwareHostPolicy is a token aware host selection policy, where hosts are
// selected based on the partition key, so queries are sent to the host which
// owns the partition. Fallback is used when routing information is not available.
func TokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy {
	return &tokenAwareHostPolicy{fallback: fallback, hosts: []HostInfo{}}
}

type tokenAwareHostPolicy struct {
	mu          sync.RWMutex
	hosts       []HostInfo
	partitioner string
	tokenRing   *tokenRing
	fallback    HostSelectionPolicy
}

func (t *tokenAwareHostPolicy) SetHosts(hosts []HostInfo) {
	t.mu.Lock()
	defer t.mu.Unlock()

	// always update the fallback
	t.fallback.SetHosts(hosts)
	t.hosts = hosts

	t.resetTokenRing()
}

func (t *tokenAwareHostPolicy) SetPartitioner(partitioner string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	if t.partitioner != partitioner {
		t.fallback.SetPartitioner(partitioner)
		t.partitioner = partitioner

		t.resetTokenRing()
	}
}

func (t *tokenAwareHostPolicy) resetTokenRing() {
	if t.partitioner == "" {
		// partitioner not yet set
		return
	}

	// create a new token ring
	tokenRing, err := newTokenRing(t.partitioner, t.hosts)
	if err != nil {
		log.Printf("Unable to update the token ring due to error: %s", err)
		return
	}

	// replace the token ring
	t.tokenRing = tokenRing
}

func (t *tokenAwareHostPolicy) Pick(qry *Query) NextHost {
	if qry == nil {
		return t.fallback.Pick(qry)
	} else if qry.binding != nil && len(qry.values) == 0 {
		// If this query was created using session.Bind we wont have the query
		// values yet, so we have to pass down to the next policy.
		// TODO: Remove this and handle this case
		return t.fallback.Pick(qry)
	}

	routingKey, err := qry.GetRoutingKey()
	if err != nil {
		return t.fallback.Pick(qry)
	}
	if routingKey == nil {
		return t.fallback.Pick(qry)
	}

	var host *HostInfo

	t.mu.RLock()
	// TODO retrieve a list of hosts based on the replication strategy
	host = t.tokenRing.GetHostForPartitionKey(routingKey)
	t.mu.RUnlock()

	if host == nil {
		return t.fallback.Pick(qry)
	}

	// scope these variables for the same lifetime as the iterator function
	var (
		hostReturned bool
		fallbackIter NextHost
	)
	return func() SelectedHost {
		if !hostReturned {
			hostReturned = true
			return selectedTokenAwareHost{host}
		}

		// fallback
		if fallbackIter == nil {
			fallbackIter = t.fallback.Pick(qry)
		}

		fallbackHost := fallbackIter()

		// filter the token aware selected hosts from the fallback hosts
		if fallbackHost.Info() == host {
			fallbackHost = fallbackIter()
		}

		return fallbackHost
	}
}

// selectedTokenAwareHost is a host returned by the tokenAwareHostPolicy and
// implements the SelectedHost interface
type selectedTokenAwareHost struct {
	info *HostInfo
}

func (host selectedTokenAwareHost) Info() *HostInfo {
	return host.info
}

func (host selectedTokenAwareHost) Mark(err error) {
	// noop
}

// HostPoolHostPolicy is a host policy which uses the bitly/go-hostpool library
// to distribute queries between hosts and prevent sending queries to
// unresponsive hosts. When creating the host pool that is passed to the policy
// use an empty slice of hosts as the hostpool will be populated later by gocql.
// See below for examples of usage:
//
//     // Create host selection policy using a simple host pool
//     cluster.PoolConfig.HostSelectionPolicy = HostPoolHostPolicy(hostpool.New(nil))
//
//     // Create host selection policy using an epsilon greddy pool
//     cluster.PoolConfig.HostSelectionPolicy = HostPoolHostPolicy(
//         hostpool.NewEpsilonGreedy(nil, 0, &hostpool.LinearEpsilonValueCalculator{}),
//     )
//
func HostPoolHostPolicy(hp hostpool.HostPool) HostSelectionPolicy {
	return &hostPoolHostPolicy{hostMap: map[string]HostInfo{}, hp: hp}
}

type hostPoolHostPolicy struct {
	hp      hostpool.HostPool
	hostMap map[string]HostInfo
	mu      sync.RWMutex
}

func (r *hostPoolHostPolicy) SetHosts(hosts []HostInfo) {
	peers := make([]string, len(hosts))
	hostMap := make(map[string]HostInfo, len(hosts))

	for i, host := range hosts {
		peers[i] = host.Peer
		hostMap[host.Peer] = host
	}

	r.mu.Lock()
	r.hp.SetHosts(peers)
	r.hostMap = hostMap
	r.mu.Unlock()
}

func (r *hostPoolHostPolicy) SetPartitioner(partitioner string) {
	// noop
}

func (r *hostPoolHostPolicy) Pick(qry *Query) NextHost {
	return func() SelectedHost {
		r.mu.RLock()
		if len(r.hostMap) == 0 {
			r.mu.RUnlock()
			return nil
		}

		hostR := r.hp.Get()
		host, ok := r.hostMap[hostR.Host()]
		if !ok {
			r.mu.RUnlock()
			return nil
		}

		return selectedHostPoolHost{&host, hostR}
	}
}

// selectedHostPoolHost is a host returned by the hostPoolHostPolicy and
// implements the SelectedHost interface
type selectedHostPoolHost struct {
	info  *HostInfo
	hostR hostpool.HostPoolResponse
}

func (host selectedHostPoolHost) Info() *HostInfo {
	return host.info
}

func (host selectedHostPoolHost) Mark(err error) {
	host.hostR.Mark(err)
}

//ConnSelectionPolicy is an interface for selecting an
//appropriate connection for executing a query
type ConnSelectionPolicy interface {
	SetConns(conns []*Conn)
	Pick(*Query) *Conn
}

type roundRobinConnPolicy struct {
	conns []*Conn
	pos   uint32
	mu    sync.RWMutex
}

func RoundRobinConnPolicy() func() ConnSelectionPolicy {
	return func() ConnSelectionPolicy {
		return &roundRobinConnPolicy{}
	}
}

func (r *roundRobinConnPolicy) SetConns(conns []*Conn) {
	r.mu.Lock()
	r.conns = conns
	r.mu.Unlock()
}

func (r *roundRobinConnPolicy) Pick(qry *Query) *Conn {
	pos := atomic.AddUint32(&r.pos, 1)
	var conn *Conn
	r.mu.RLock()
	if len(r.conns) > 0 {
		conn = r.conns[pos%uint32(len(r.conns))]
	}
	r.mu.RUnlock()
	return conn
}
<commit_msg>Fix deadlock with HostPoolHostPolicy<commit_after>// Copyright (c) 2012 The gocql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//This file will be the future home for more policies
package gocql

import (
	"log"
	"sync"
	"sync/atomic"

	"github.com/hailocab/go-hostpool"
)

// RetryableQuery is an interface that represents a query or batch statement that
// exposes the correct functions for the retry policy logic to evaluate correctly.
type RetryableQuery interface {
	Attempts() int
	GetConsistency() Consistency
}

// RetryPolicy interface is used by gocql to determine if a query can be attempted
// again after a retryable error has been received. The interface allows gocql
// users to implement their own logic to determine if a query can be attempted
// again.
//
// See SimpleRetryPolicy as an example of implementing and using a RetryPolicy
// interface.
type RetryPolicy interface {
	Attempt(RetryableQuery) bool
}

// SimpleRetryPolicy has simple logic for attempting a query a fixed number of times.
//
// See below for examples of usage:
//
//     //Assign to the cluster
//     cluster.RetryPolicy = &gocql.SimpleRetryPolicy{NumRetries: 3}
//
//     //Assign to a query
//     query.RetryPolicy(&gocql.SimpleRetryPolicy{NumRetries: 1})
//
type SimpleRetryPolicy struct {
	NumRetries int //Number of times to retry a query
}

// Attempt tells gocql to attempt the query again based on query.Attempts being less
// than the NumRetries defined in the policy.
func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool {
	return q.Attempts() <= s.NumRetries
}

// HostSelectionPolicy is an interface for selecting
// the most appropriate host to execute a given query.
type HostSelectionPolicy interface {
	SetHosts
	SetPartitioner
	//Pick returns an iteration function over selected hosts
	Pick(*Query) NextHost
}

// SelectedHost is an interface returned when picking a host from a host
// selection policy.
type SelectedHost interface {
	Info() *HostInfo
	Mark(error)
}

// NextHost is an iteration function over picked hosts
type NextHost func() SelectedHost

// RoundRobinHostPolicy is a round-robin load balancing policy, where each host
// is tried sequentially for each query.
func RoundRobinHostPolicy() HostSelectionPolicy {
	return &roundRobinHostPolicy{hosts: []HostInfo{}}
}

type roundRobinHostPolicy struct {
	hosts []HostInfo
	pos   uint32
	mu    sync.RWMutex
}

func (r *roundRobinHostPolicy) SetHosts(hosts []HostInfo) {
	r.mu.Lock()
	r.hosts = hosts
	r.mu.Unlock()
}

func (r *roundRobinHostPolicy) SetPartitioner(partitioner string) {
	// noop
}

func (r *roundRobinHostPolicy) Pick(qry *Query) NextHost {
	// i is used to limit the number of attempts to find a host
	// to the number of hosts known to this policy
	var i uint32 = 0
	return func() SelectedHost {
		r.mu.RLock()
		if len(r.hosts) == 0 {
			r.mu.RUnlock()
			return nil
		}

		var host *HostInfo
		// always increment pos to evenly distribute traffic in case of
		// failures
		pos := atomic.AddUint32(&r.pos, 1)
		if int(i) < len(r.hosts) {
			host = &r.hosts[(pos)%uint32(len(r.hosts))]
			i++
		}
		r.mu.RUnlock()
		return selectedRoundRobinHost{host}
	}
}

// selectedRoundRobinHost is a host returned by the roundRobinHostPolicy and
// implements the SelectedHost interface
type selectedRoundRobinHost struct {
	info *HostInfo
}

func (host selectedRoundRobinHost) Info() *HostInfo {
	return host.info
}

func (host selectedRoundRobinHost) Mark(err error) {
	// noop
}

// TokenAwareHostPolicy is a token aware host selection policy, where hosts are
// selected based on the partition key, so queries are sent to the host which
// owns the partition. Fallback is used when routing information is not available.
func TokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy {
	return &tokenAwareHostPolicy{fallback: fallback, hosts: []HostInfo{}}
}

type tokenAwareHostPolicy struct {
	mu          sync.RWMutex
	hosts       []HostInfo
	partitioner string
	tokenRing   *tokenRing
	fallback    HostSelectionPolicy
}

func (t *tokenAwareHostPolicy) SetHosts(hosts []HostInfo) {
	t.mu.Lock()
	defer t.mu.Unlock()

	// always update the fallback
	t.fallback.SetHosts(hosts)
	t.hosts = hosts

	t.resetTokenRing()
}

func (t *tokenAwareHostPolicy) SetPartitioner(partitioner string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	if t.partitioner != partitioner {
		t.fallback.SetPartitioner(partitioner)
		t.partitioner = partitioner

		t.resetTokenRing()
	}
}

func (t *tokenAwareHostPolicy) resetTokenRing() {
	if t.partitioner == "" {
		// partitioner not yet set
		return
	}

	// create a new token ring
	tokenRing, err := newTokenRing(t.partitioner, t.hosts)
	if err != nil {
		log.Printf("Unable to update the token ring due to error: %s", err)
		return
	}

	// replace the token ring
	t.tokenRing = tokenRing
}

func (t *tokenAwareHostPolicy) Pick(qry *Query) NextHost {
	if qry == nil {
		return t.fallback.Pick(qry)
	} else if qry.binding != nil && len(qry.values) == 0 {
		// If this query was created using session.Bind we wont have the query
		// values yet, so we have to pass down to the next policy.
		// TODO: Remove this and handle this case
		return t.fallback.Pick(qry)
	}

	routingKey, err := qry.GetRoutingKey()
	if err != nil {
		return t.fallback.Pick(qry)
	}
	if routingKey == nil {
		return t.fallback.Pick(qry)
	}

	var host *HostInfo

	t.mu.RLock()
	// TODO retrieve a list of hosts based on the replication strategy
	host = t.tokenRing.GetHostForPartitionKey(routingKey)
	t.mu.RUnlock()

	if host == nil {
		return t.fallback.Pick(qry)
	}

	// scope these variables for the same lifetime as the iterator function
	var (
		hostReturned bool
		fallbackIter NextHost
	)
	return func() SelectedHost {
		if !hostReturned {
			hostReturned = true
			return selectedTokenAwareHost{host}
		}

		// fallback
		if fallbackIter == nil {
			fallbackIter = t.fallback.Pick(qry)
		}

		fallbackHost := fallbackIter()

		// filter the token aware selected hosts from the fallback hosts
		if fallbackHost.Info() == host {
			fallbackHost = fallbackIter()
		}

		return fallbackHost
	}
}

// selectedTokenAwareHost is a host returned by the tokenAwareHostPolicy and
// implements the SelectedHost interface
type selectedTokenAwareHost struct {
	info *HostInfo
}

func (host selectedTokenAwareHost) Info() *HostInfo {
	return host.info
}

func (host selectedTokenAwareHost) Mark(err error) {
	// noop
}

// HostPoolHostPolicy is a host policy which uses the bitly/go-hostpool library
// to distribute queries between hosts and prevent sending queries to
// unresponsive hosts. When creating the host pool that is passed to the policy
// use an empty slice of hosts as the hostpool will be populated later by gocql.
// See below for examples of usage:
//
//     // Create host selection policy using a simple host pool
//     cluster.PoolConfig.HostSelectionPolicy = HostPoolHostPolicy(hostpool.New(nil))
//
//     // Create host selection policy using an epsilon greddy pool
//     cluster.PoolConfig.HostSelectionPolicy = HostPoolHostPolicy(
//         hostpool.NewEpsilonGreedy(nil, 0, &hostpool.LinearEpsilonValueCalculator{}),
//     )
//
func HostPoolHostPolicy(hp hostpool.HostPool) HostSelectionPolicy {
	return &hostPoolHostPolicy{hostMap: map[string]HostInfo{}, hp: hp}
}

type hostPoolHostPolicy struct {
	hp      hostpool.HostPool
	hostMap map[string]HostInfo
	mu      sync.RWMutex
}

func (r *hostPoolHostPolicy) SetHosts(hosts []HostInfo) {
	peers := make([]string, len(hosts))
	hostMap := make(map[string]HostInfo, len(hosts))

	for i, host := range hosts {
		peers[i] = host.Peer
		hostMap[host.Peer] = host
	}

	r.mu.Lock()
	r.hp.SetHosts(peers)
	r.hostMap = hostMap
	r.mu.Unlock()
}

func (r *hostPoolHostPolicy) SetPartitioner(partitioner string) {
	// noop
}

func (r *hostPoolHostPolicy) Pick(qry *Query) NextHost {
	return func() SelectedHost {
		r.mu.RLock()
		defer r.mu.RUnlock()

		if len(r.hostMap) == 0 {
			return nil
		}

		hostR := r.hp.Get()
		host, ok := r.hostMap[hostR.Host()]
		if !ok {
			return nil
		}

		return selectedHostPoolHost{&host, hostR}
	}
}

// selectedHostPoolHost is a host returned by the hostPoolHostPolicy and
// implements the SelectedHost interface
type selectedHostPoolHost struct {
	info  *HostInfo
	hostR hostpool.HostPoolResponse
}

func (host selectedHostPoolHost) Info() *HostInfo {
	return host.info
}

func (host selectedHostPoolHost) Mark(err error) {
	host.hostR.Mark(err)
}

//ConnSelectionPolicy is an interface for selecting an
//appropriate connection for executing a query
type ConnSelectionPolicy interface {
	SetConns(conns []*Conn)
	Pick(*Query) *Conn
}

type roundRobinConnPolicy struct {
	conns []*Conn
	pos   uint32
	mu    sync.RWMutex
}

func RoundRobinConnPolicy() func() ConnSelectionPolicy {
	return func() ConnSelectionPolicy {
		return &roundRobinConnPolicy{}
	}
}

func (r *roundRobinConnPolicy) SetConns(conns []*Conn) {
	r.mu.Lock()
	r.conns = conns
	r.mu.Unlock()
}

func (r *roundRobinConnPolicy) Pick(qry *Query) *Conn {
	pos := atomic.AddUint32(&r.pos, 1)
	var conn *Conn
	r.mu.RLock()
	if len(r.conns) > 0 {
		conn = r.conns[pos%uint32(len(r.conns))]
	}
	r.mu.RUnlock()
	return conn
}
<|endoftext|>


<commit_before>// Package polyline implements a Google Maps Encoding Polyline encoder and
// decoder. See
// https://developers.google.com/maps/documentation/utilities/polylinealgorithm.
//
// The default codec encodes and decodes two-dimensional coordinates scaled by
// 1e5. For other dimensionalities and scales create a custom Codec.
//
// The package operates on byte slices. Encoding functions take an existing byte
// slice as input (which can be nil) and return a new byte slice with the
// encoded value appended to it, similarly to how Go's append function works. To
// increase performance, you can pre-allocate byte slices, for example by
// passing make([]byte, 0, 128) as the input byte slice. Similarly, decoding
// functions take a byte slice as input and return the remaining unconsumed
// bytes as output.
package polyline

import (
	"errors"
	"math"
)

var (
	errDimensionalMismatch  = errors.New("dimensional mismatch")
	errInvalidByte          = errors.New("invalid byte")
	errUnterminatedSequence = errors.New("unterminated sequence")
)

func round(x float64) int {
	if x < 0 {
		return int(-math.Floor(-x + 0.5))
	}
	return int(math.Floor(x + 0.5))
}

// A Codec represents an encoder.
type Codec struct {
	Dim   int     // Dimensionality, normally 2
	Scale float64 // Scale, normally 1e5
}

var defaultCodec = Codec{Dim: 2, Scale: 1e5}

// DecodeUint decodes a single unsigned integer from buf. It returns the decoded
// uint, the remaining unconsumed bytes of buf, and any error.
func DecodeUint(buf []byte) (uint, []byte, error) {
	var u, shift uint
	for i, b := range buf {
		switch {
		case 63 <= b && b < 95:
			u += (uint(b) - 63) << shift
			return u, buf[i+1:], nil
		case 95 <= b && b < 127:
			u += (uint(b) - 95) << shift
			shift += 5
		default:
			return 0, nil, errInvalidByte
		}
	}
	return 0, nil, errUnterminatedSequence
}

// DecodeInt decodes a single signed integer from buf. It returns the decoded
// int, the remaining unconsumed bytes of buf, and any error.
func DecodeInt(buf []byte) (int, []byte, error) {
	u, buf, err := DecodeUint(buf)
	if err != nil {
		return 0, nil, err
	}
	if u&1 == 0 {
		return int(u >> 1), buf, nil
	}
	return -int((u + 1) >> 1), buf, nil
}

// EncodeUint appends the encoding of a single unsigned integer u to buf and
// returns the new buf.
func EncodeUint(buf []byte, u uint) []byte {
	for u >= 32 {
		buf = append(buf, byte((u&31)+95))
		u >>= 5
	}
	buf = append(buf, byte(u+63))
	return buf
}

// EncodeInt appends the encoding of a single signed integer i to buf and
// returns the new buf.
func EncodeInt(buf []byte, i int) []byte {
	var u uint
	if i < 0 {
		u = uint(^(i << 1))
	} else {
		u = uint(i << 1)
	}
	return EncodeUint(buf, u)
}

// DecodeCoord decodes a single coordinate from buf. It returns the coordinate,
// the remaining unconsumed bytes of buf, and any error.
func (c Codec) DecodeCoord(buf []byte) ([]float64, []byte, error) {
	coord := make([]float64, c.Dim)
	for i := range coord {
		var err error
		var j int
		j, buf, err = DecodeInt(buf)
		if err != nil {
			return nil, nil, err
		}
		coord[i] = float64(j) / c.Scale
	}
	return coord, buf, nil
}

// DecodeCoords decodes an array of coordinates from buf. It returns the
// coordinates, the remaining unconsumed bytes of buf, and any error.
func (c Codec) DecodeCoords(buf []byte) ([][]float64, []byte, error) {
	var coord []float64
	var err error
	coord, buf, err = c.DecodeCoord(buf)
	if err != nil {
		return nil, nil, err
	}
	coords := [][]float64{coord}
	for i := 1; len(buf) > 0; i++ {
		coord, buf, err = c.DecodeCoord(buf)
		if err != nil {
			return nil, nil, err
		}
		for j := range coord {
			coord[j] += coords[i-1][j]
		}
		coords = append(coords, coord)
	}
	return coords, nil, nil
}

// DecodeFlatCoords decodes coordinates from buf, appending them to a
// one-dimensional array. It returns the coordinates, the remaining unconsumed
// bytes in buf, and any error.
func (c Codec) DecodeFlatCoords(fcs []float64, buf []byte) ([]float64, []byte, error) {
	if len(fcs)%c.Dim != 0 {
		return nil, nil, errDimensionalMismatch
	}
	last := make([]int, c.Dim)
	for len(buf) > 0 {
		for j := 0; j < c.Dim; j++ {
			var err error
			var k int
			k, buf, err = DecodeInt(buf)
			if err != nil {
				return nil, nil, err
			}
			last[j] += k
			fcs = append(fcs, float64(last[j])/c.Scale)
		}
	}
	return fcs, nil, nil
}

// EncodeCoord encodes a single coordinate to buf and returns the new buf.
func (c Codec) EncodeCoord(buf []byte, coord []float64) []byte {
	for _, x := range coord {
		buf = EncodeInt(buf, round(c.Scale*x))
	}
	return buf
}

// EncodeCoords appends the encoding of an array of coordinates coords to buf
// and returns the new buf.
func (c Codec) EncodeCoords(buf []byte, coords [][]float64) []byte {
	last := make([]int, c.Dim)
	for _, coord := range coords {
		for i, x := range coord {
			ex := round(c.Scale * x)
			buf = EncodeInt(buf, ex-last[i])
			last[i] = ex
		}
	}
	return buf
}

// EncodeFlatCoords encodes a one-dimensional array of coordinates to buf. It
// returns the new buf and any error.
func (c Codec) EncodeFlatCoords(buf []byte, fcs []float64) ([]byte, error) {
	if len(fcs)%c.Dim != 0 {
		return nil, errDimensionalMismatch
	}
	last := make([]int, c.Dim)
	for i, x := range fcs {
		ex := round(c.Scale * x)
		j := i % c.Dim
		buf = EncodeInt(buf, ex-last[j])
		last[j] = ex
	}
	return buf, nil
}

// DecodeCoord decodes a single coordinate from buf using the default codec. It
// returns the coordinate, the remaining bytes in buf, and any error.
func DecodeCoord(buf []byte) ([]float64, []byte, error) {
	return defaultCodec.DecodeCoord(buf)
}

// DecodeCoords decodes an array of coordinates from buf using the default
// codec. It returns the coordinates, the remaining bytes in buf, and any error.
func DecodeCoords(buf []byte) ([][]float64, []byte, error) {
	return defaultCodec.DecodeCoords(buf)
}

// EncodeCoord returns the encoding of an array of coordinates using the default
// codec.
func EncodeCoord(coord []float64) []byte {
	return defaultCodec.EncodeCoord(nil, coord)
}

// EncodeCoords returns the encoding of an array of coordinates using the
// default codec.
func EncodeCoords(coords [][]float64) []byte {
	return defaultCodec.EncodeCoords(nil, coords)
}
<commit_msg>Rename variable<commit_after>// Package polyline implements a Google Maps Encoding Polyline encoder and
// decoder. See
// https://developers.google.com/maps/documentation/utilities/polylinealgorithm.
//
// The default codec encodes and decodes two-dimensional coordinates scaled by
// 1e5. For other dimensionalities and scales create a custom Codec.
//
// The package operates on byte slices. Encoding functions take an existing byte
// slice as input (which can be nil) and return a new byte slice with the
// encoded value appended to it, similarly to how Go's append function works. To
// increase performance, you can pre-allocate byte slices, for example by
// passing make([]byte, 0, 128) as the input byte slice. Similarly, decoding
// functions take a byte slice as input and return the remaining unconsumed
// bytes as output.
package polyline

import (
	"errors"
	"math"
)

var (
	errDimensionalMismatch  = errors.New("dimensional mismatch")
	errInvalidByte          = errors.New("invalid byte")
	errUnterminatedSequence = errors.New("unterminated sequence")
)

func round(x float64) int {
	if x < 0 {
		return int(-math.Floor(-x + 0.5))
	}
	return int(math.Floor(x + 0.5))
}

// A Codec represents an encoder.
type Codec struct {
	Dim   int     // Dimensionality, normally 2
	Scale float64 // Scale, normally 1e5
}

var defaultCodec = Codec{Dim: 2, Scale: 1e5}

// DecodeUint decodes a single unsigned integer from buf. It returns the decoded
// uint, the remaining unconsumed bytes of buf, and any error.
func DecodeUint(buf []byte) (uint, []byte, error) {
	var u, shift uint
	for i, b := range buf {
		switch {
		case 63 <= b && b < 95:
			u += (uint(b) - 63) << shift
			return u, buf[i+1:], nil
		case 95 <= b && b < 127:
			u += (uint(b) - 95) << shift
			shift += 5
		default:
			return 0, nil, errInvalidByte
		}
	}
	return 0, nil, errUnterminatedSequence
}

// DecodeInt decodes a single signed integer from buf. It returns the decoded
// int, the remaining unconsumed bytes of buf, and any error.
func DecodeInt(buf []byte) (int, []byte, error) {
	u, buf, err := DecodeUint(buf)
	if err != nil {
		return 0, nil, err
	}
	if u&1 == 0 {
		return int(u >> 1), buf, nil
	}
	return -int((u + 1) >> 1), buf, nil
}

// EncodeUint appends the encoding of a single unsigned integer u to buf and
// returns the new buf.
func EncodeUint(buf []byte, u uint) []byte {
	for u >= 32 {
		buf = append(buf, byte((u&31)+95))
		u >>= 5
	}
	buf = append(buf, byte(u+63))
	return buf
}

// EncodeInt appends the encoding of a single signed integer i to buf and
// returns the new buf.
func EncodeInt(buf []byte, i int) []byte {
	var u uint
	if i < 0 {
		u = uint(^(i << 1))
	} else {
		u = uint(i << 1)
	}
	return EncodeUint(buf, u)
}

// DecodeCoord decodes a single coordinate from buf. It returns the coordinate,
// the remaining unconsumed bytes of buf, and any error.
func (c Codec) DecodeCoord(buf []byte) ([]float64, []byte, error) {
	coord := make([]float64, c.Dim)
	for i := range coord {
		var err error
		var j int
		j, buf, err = DecodeInt(buf)
		if err != nil {
			return nil, nil, err
		}
		coord[i] = float64(j) / c.Scale
	}
	return coord, buf, nil
}

// DecodeCoords decodes an array of coordinates from buf. It returns the
// coordinates, the remaining unconsumed bytes of buf, and any error.
func (c Codec) DecodeCoords(buf []byte) ([][]float64, []byte, error) {
	var coord []float64
	var err error
	coord, buf, err = c.DecodeCoord(buf)
	if err != nil {
		return nil, nil, err
	}
	coords := [][]float64{coord}
	for i := 1; len(buf) > 0; i++ {
		coord, buf, err = c.DecodeCoord(buf)
		if err != nil {
			return nil, nil, err
		}
		for j := range coord {
			coord[j] += coords[i-1][j]
		}
		coords = append(coords, coord)
	}
	return coords, nil, nil
}

// DecodeFlatCoords decodes coordinates from buf, appending them to a
// one-dimensional array. It returns the coordinates, the remaining unconsumed
// bytes in buf, and any error.
func (c Codec) DecodeFlatCoords(flatCoords []float64, buf []byte) ([]float64, []byte, error) {
	if len(flatCoords)%c.Dim != 0 {
		return nil, nil, errDimensionalMismatch
	}
	last := make([]int, c.Dim)
	for len(buf) > 0 {
		for j := 0; j < c.Dim; j++ {
			var err error
			var k int
			k, buf, err = DecodeInt(buf)
			if err != nil {
				return nil, nil, err
			}
			last[j] += k
			flatCoords = append(flatCoords, float64(last[j])/c.Scale)
		}
	}
	return flatCoords, nil, nil
}

// EncodeCoord encodes a single coordinate to buf and returns the new buf.
func (c Codec) EncodeCoord(buf []byte, coord []float64) []byte {
	for _, x := range coord {
		buf = EncodeInt(buf, round(c.Scale*x))
	}
	return buf
}

// EncodeCoords appends the encoding of an array of coordinates coords to buf
// and returns the new buf.
func (c Codec) EncodeCoords(buf []byte, coords [][]float64) []byte {
	last := make([]int, c.Dim)
	for _, coord := range coords {
		for i, x := range coord {
			ex := round(c.Scale * x)
			buf = EncodeInt(buf, ex-last[i])
			last[i] = ex
		}
	}
	return buf
}

// EncodeFlatCoords encodes a one-dimensional array of coordinates to buf. It
// returns the new buf and any error.
func (c Codec) EncodeFlatCoords(buf []byte, flatCoords []float64) ([]byte, error) {
	if len(flatCoords)%c.Dim != 0 {
		return nil, errDimensionalMismatch
	}
	last := make([]int, c.Dim)
	for i, x := range flatCoords {
		ex := round(c.Scale * x)
		j := i % c.Dim
		buf = EncodeInt(buf, ex-last[j])
		last[j] = ex
	}
	return buf, nil
}

// DecodeCoord decodes a single coordinate from buf using the default codec. It
// returns the coordinate, the remaining bytes in buf, and any error.
func DecodeCoord(buf []byte) ([]float64, []byte, error) {
	return defaultCodec.DecodeCoord(buf)
}

// DecodeCoords decodes an array of coordinates from buf using the default
// codec. It returns the coordinates, the remaining bytes in buf, and any error.
func DecodeCoords(buf []byte) ([][]float64, []byte, error) {
	return defaultCodec.DecodeCoords(buf)
}

// EncodeCoord returns the encoding of an array of coordinates using the default
// codec.
func EncodeCoord(coord []float64) []byte {
	return defaultCodec.EncodeCoord(nil, coord)
}

// EncodeCoords returns the encoding of an array of coordinates using the
// default codec.
func EncodeCoords(coords [][]float64) []byte {
	return defaultCodec.EncodeCoords(nil, coords)
}
<|endoftext|>


<commit_before>package enforcer

import (
	"fmt"

	"github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/database"
)

type Enforcer interface {
	Enforce() error
}

type impl struct {
    violatorRepo, reformerRepo database.Repo
}

func NewEnforcer(violatorRepo, reformerRepo database.Repo) Enforcer {
	return &impl{
        violatorRepo: violatorRepo,
        reformerRepo: reformerRepo,
	}
}

func (e impl) Enforce() error {
	fmt.Printf("enforcing\n")

	e.revokePrivilegesFromViolators()
	e.grantPrivilegesToReformed()

	return nil
}

func (e impl) revokePrivilegesFromViolators() error {
	violators, err := e.violatorRepo.All()
	if err != nil {
		return err
	}

	for _, db := range violators {
        db.RevokePrivileges()
        db.ResetActivePrivileges()
	}
	return nil
}

func (e impl) grantPrivilegesToReformed() error {
	reformers, err := e.reformerRepo.All()
	if err != nil {
		return err
	}

	for _, db := range reformers {
        db.GrantPrivileges()
        db.ResetActivePrivileges()
	}

	return nil
}
<commit_msg>Do not print to stdout when enforcing.<commit_after>package enforcer

import "github.com/pivotal-cf-experimental/cf-mysql-quota-enforcer/database"

type Enforcer interface {
	Enforce() error
}

type impl struct {
	violatorRepo, reformerRepo database.Repo
}

func NewEnforcer(violatorRepo, reformerRepo database.Repo) Enforcer {
	return &impl{
		violatorRepo: violatorRepo,
		reformerRepo: reformerRepo,
	}
}

func (e impl) Enforce() error {
	e.revokePrivilegesFromViolators()
	e.grantPrivilegesToReformed()

	return nil
}

func (e impl) revokePrivilegesFromViolators() error {
	violators, err := e.violatorRepo.All()
	if err != nil {
		return err
	}

	for _, db := range violators {
		db.RevokePrivileges()
		db.ResetActivePrivileges()
	}
	return nil
}

func (e impl) grantPrivilegesToReformed() error {
	reformers, err := e.reformerRepo.All()
	if err != nil {
		return err
	}

	for _, db := range reformers {
		db.GrantPrivileges()
		db.ResetActivePrivileges()
	}

	return nil
}
<|endoftext|>


<commit_before>package engine

// Directory Index

import (
	"bytes"
	"net/http"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"
	"github.com/xyproto/algernon/themes"
	"github.com/xyproto/algernon/utils"
	"gopkg.in/gcfg.v1"
)

var (
	// List of filenames that should be displayed instead of a directory listing
	indexFilenames = []string{"index.lua", "index.html", "index.md", "index.txt", "index.pongo2", "index.amber", "index.tmpl", "index.po2", "index.happ", "index.hyper", "index.hyper.js", "index.hyper.jsx"}

	doubleP  = utils.Pathsep + utils.Pathsep /* // */
	dotSlash = "." + utils.Pathsep           /* ./ */
)

const (
	dirconfFilename = ".algernon"
)

// directory configuration file structure
type DirConfig struct {
	Main struct {
		Title string
		Theme string
	}
}

// DirectoryListing serves the given directory as a web page with links the the contents
func (ac *Config) DirectoryListing(w http.ResponseWriter, req *http.Request, rootdir, dirname, theme string) {
	var (
		buf          bytes.Buffer
		fullFilename string
		URLpath      string
		title        = dirname
	)

	// Fill the coming HTML body with a list of all the filenames in `dirname`
	for _, filename := range utils.GetFilenames(dirname) {

		if filename == dirconfFilename {
			// Skip
			continue
		}

		// Find the full name
		fullFilename = filepath.Join(dirname, filename)

		// Remove the root directory from the link path
		URLpath = fullFilename[len(rootdir)+1:]

		// Output different entries for files and directories
		buf.WriteString(themes.HTMLLink(filename, URLpath, ac.fs.IsDir(fullFilename)))
	}

	// Read directory configuration, if present
	fullDirConfFilename := filepath.Join(dirname, dirconfFilename)
	if ac.fs.Exists(fullDirConfFilename) {
		var dirConf DirConfig
		if err := gcfg.ReadFileInto(&dirConf, fullDirConfFilename); err == nil {
			if dirConf.Main.Title != "" {
				title = dirConf.Main.Title
			}
			if dirConf.Main.Theme != "" {
				theme = dirConf.Main.Theme
			}
		}
	} else {
		// Strip the leading "./" from the current directory
		title = strings.TrimPrefix(title, dotSlash)

		// Strip double "/" at the end, just keep one
		if strings.Contains(title, doubleP) {
			// Replace "//" with just "/"
			title = strings.Replace(title, doubleP, utils.Pathsep, utils.EveryInstance)
		}
	}

	// Check if the current page contents are empty
	if buf.Len() == 0 {
		buf.WriteString("Empty directory")
	}

	htmldata := themes.MessagePageBytes(title, buf.Bytes(), theme)

	// If the auto-refresh feature has been enabled
	if ac.autoRefreshMode {
		// Insert JavaScript for refreshing the page into the generated HTML
		htmldata = ac.InsertAutoRefresh(req, htmldata)
	}

	// Serve the page
	w.Header().Add("Content-Type", "text/html; charset=utf-8")
	DataToClient(w, req, dirname, htmldata)
}

// DirPage serves a directory, using index.* files, if present.
// The directory must exist.
// rootdir is the base directory (can be ".")
// dirname is the specific directory that is to be served (should never be ".")
func (ac *Config) DirPage(w http.ResponseWriter, req *http.Request, rootdir, dirname, theme string) {

	// Check if we are instructed to quit after serving the first file
	if ac.quitAfterFirstRequest {
		go ac.quitSoon("Quit after first request", defaultSoonDuration)
	}

	// If the URL does not end with a slash, redirect to an URL that does
	if !strings.HasSuffix(req.URL.Path, "/") {
		if req.Method == "POST" {
			log.Warn("Redirecting a POST request: " + req.URL.Path + " -> " + req.URL.Path + "/.")
			log.Warn("Header data may be lost! Please add the missing slash.")
		}
		http.Redirect(w, req, req.URL.Path+"/", http.StatusMovedPermanently)
		return
	}

	// Handle the serving of index files, if needed
	var filename string
	for _, indexfile := range indexFilenames {
		filename = filepath.Join(dirname, indexfile)
		if ac.fs.Exists(filename) {
			ac.FilePage(w, req, filename, ac.defaultLuaDataFilename)
			return
		}
	}

	// Serve a directory listing of no index file is found
	ac.DirectoryListing(w, req, rootdir, dirname, theme)
}
<commit_msg>Reorder index files<commit_after>package engine

// Directory Index

import (
	"bytes"
	"net/http"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"
	"github.com/xyproto/algernon/themes"
	"github.com/xyproto/algernon/utils"
	"gopkg.in/gcfg.v1"
)

var (
	// List of filenames that should be displayed instead of a directory listing
	indexFilenames = []string{"index.lua", "index.html", "index.md", "index.txt", "index.pongo2", "index.tmpl", "index.po2", "index.amber", "index.happ", "index.hyper", "index.hyper.js", "index.hyper.jsx"}

	doubleP  = utils.Pathsep + utils.Pathsep /* // */
	dotSlash = "." + utils.Pathsep           /* ./ */
)

const (
	dirconfFilename = ".algernon"
)

// directory configuration file structure
type DirConfig struct {
	Main struct {
		Title string
		Theme string
	}
}

// DirectoryListing serves the given directory as a web page with links the the contents
func (ac *Config) DirectoryListing(w http.ResponseWriter, req *http.Request, rootdir, dirname, theme string) {
	var (
		buf          bytes.Buffer
		fullFilename string
		URLpath      string
		title        = dirname
	)

	// Fill the coming HTML body with a list of all the filenames in `dirname`
	for _, filename := range utils.GetFilenames(dirname) {

		if filename == dirconfFilename {
			// Skip
			continue
		}

		// Find the full name
		fullFilename = filepath.Join(dirname, filename)

		// Remove the root directory from the link path
		URLpath = fullFilename[len(rootdir)+1:]

		// Output different entries for files and directories
		buf.WriteString(themes.HTMLLink(filename, URLpath, ac.fs.IsDir(fullFilename)))
	}

	// Read directory configuration, if present
	fullDirConfFilename := filepath.Join(dirname, dirconfFilename)
	if ac.fs.Exists(fullDirConfFilename) {
		var dirConf DirConfig
		if err := gcfg.ReadFileInto(&dirConf, fullDirConfFilename); err == nil {
			if dirConf.Main.Title != "" {
				title = dirConf.Main.Title
			}
			if dirConf.Main.Theme != "" {
				theme = dirConf.Main.Theme
			}
		}
	} else {
		// Strip the leading "./" from the current directory
		title = strings.TrimPrefix(title, dotSlash)

		// Strip double "/" at the end, just keep one
		if strings.Contains(title, doubleP) {
			// Replace "//" with just "/"
			title = strings.Replace(title, doubleP, utils.Pathsep, utils.EveryInstance)
		}
	}

	// Check if the current page contents are empty
	if buf.Len() == 0 {
		buf.WriteString("Empty directory")
	}

	htmldata := themes.MessagePageBytes(title, buf.Bytes(), theme)

	// If the auto-refresh feature has been enabled
	if ac.autoRefreshMode {
		// Insert JavaScript for refreshing the page into the generated HTML
		htmldata = ac.InsertAutoRefresh(req, htmldata)
	}

	// Serve the page
	w.Header().Add("Content-Type", "text/html; charset=utf-8")
	DataToClient(w, req, dirname, htmldata)
}

// DirPage serves a directory, using index.* files, if present.
// The directory must exist.
// rootdir is the base directory (can be ".")
// dirname is the specific directory that is to be served (should never be ".")
func (ac *Config) DirPage(w http.ResponseWriter, req *http.Request, rootdir, dirname, theme string) {

	// Check if we are instructed to quit after serving the first file
	if ac.quitAfterFirstRequest {
		go ac.quitSoon("Quit after first request", defaultSoonDuration)
	}

	// If the URL does not end with a slash, redirect to an URL that does
	if !strings.HasSuffix(req.URL.Path, "/") {
		if req.Method == "POST" {
			log.Warn("Redirecting a POST request: " + req.URL.Path + " -> " + req.URL.Path + "/.")
			log.Warn("Header data may be lost! Please add the missing slash.")
		}
		http.Redirect(w, req, req.URL.Path+"/", http.StatusMovedPermanently)
		return
	}

	// Handle the serving of index files, if needed
	var filename string
	for _, indexfile := range indexFilenames {
		filename = filepath.Join(dirname, indexfile)
		if ac.fs.Exists(filename) {
			ac.FilePage(w, req, filename, ac.defaultLuaDataFilename)
			return
		}
	}

	// Serve a directory listing of no index file is found
	ac.DirectoryListing(w, req, rootdir, dirname, theme)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
	"unicode/utf8"
)

var str = "hello"
var map1 = map[string]int{"one": 1, "two": 2, "three": 3}

type robot struct {
	name  string
	power int
}

type human struct {
	name  string
	power int
}

type worker interface {
	work() int
}

func (a *robot) work() int {
	fmt.Println("I'm working")
	return a.power
}

func (a *human) work() int {
	fmt.Println("I'm working")
	return a.power
}

func practise() {
	// stringPractise()
	// mapPractise()
	// structPractise()
	interfacePractise()
}

func stringPractise() {
	modifyString()
	subString()
	iterateString()
	stringLen()
	stringJoin()
}

func modifyString() {
	c := []byte(str)
	c[0] = 'w'
	fmt.Println(string(c))
}

func subString() {
	s1 := str[2:4]
	fmt.Println(s1)
	s2 := str[1:]
	fmt.Println(s2)
}

func iterateString() {
	for ix, c := range str {
		fmt.Printf("idx: %d, char: %c\n", ix, c)
	}
}

func stringLen() {
	fmt.Println("str len is", len(str))
	fmt.Println("str len is", utf8.RuneCountInString(str))
}

func stringJoin() {
	str2 := "GO1|The ABC of Go|25"
	sl2 := strings.Split(str2, "|")
	str3 := strings.Join(sl2, ";")
	fmt.Printf("sl2 joined result %s\n", str3)

	str4 := " world"
	str4 = str + str4
	fmt.Println(str4)
}

func mapPractise() {
	for ix, v := range map1 {
		fmt.Println("idx:", ix, "value:", v)
	}

	key1 := "two"
	if v, present := map1[key1]; present {
		fmt.Println(v)
	}

	delete(map1, key1)
	if v, present := map1[key1]; present {
		fmt.Println(v)
	} else {
		fmt.Println("key does not exist")
	}
}

func structPractise() {
	robot1 := new(robot)
	robot1.name = "Kfc443"
	robot1.power = 5
	fmt.Println(robot1)

	robot2 := &robot{"Mlc80", 999}
	fmt.Println(robot2)

	robot3 := newRobot("Ll88", 777)
	fmt.Println(robot3)
}

func newRobot(name string, power int) *robot {
	return &robot{name, power}
}

func interfacePractise() {
	var worker1 worker
	a := newRobot("Tom", 20)
	worker1 = a

	if _, ok := worker1.(*robot); ok {
		fmt.Println("worker is a robot!")
	}

	b := &human{"Lilei", 5}
	worker1 = b
	switch worker1.(type) {
	case *robot:
		fmt.Println("worker is a robot!")
	case *human:
		fmt.Println("worker is a human!")
	default:
		fmt.Println("worker is unknown!")
	}
}
<commit_msg>update<commit_after>package main

import (
	"fmt"
	"log"
	"net"
	"strings"
	"unicode/utf8"
)

var str = "hello"
var map1 = map[string]int{"one": 1, "two": 2, "three": 3}

type robot struct {
	name  string
	power int
}

type human struct {
	name  string
	power int
}

type worker interface {
	work() int
}

func (a *robot) work() int {
	fmt.Println("I'm working")
	return a.power
}

func (a *human) work() int {
	fmt.Println("I'm working")
	return a.power
}

func practise() {
	// stringPractise()
	// mapPractise()
	// structPractise()
	// interfacePractise()
	tcpPractise()
}

func stringPractise() {
	modifyString()
	subString()
	iterateString()
	stringLen()
	stringJoin()
}

func modifyString() {
	c := []byte(str)
	c[0] = 'w'
	fmt.Println(string(c))
}

func subString() {
	s1 := str[2:4]
	fmt.Println(s1)
	s2 := str[1:]
	fmt.Println(s2)
}

func iterateString() {
	for ix, c := range str {
		fmt.Printf("idx: %d, char: %c\n", ix, c)
	}
}

func stringLen() {
	fmt.Println("str len is", len(str))
	fmt.Println("str len is", utf8.RuneCountInString(str))
}

func stringJoin() {
	str2 := "GO1|The ABC of Go|25"
	sl2 := strings.Split(str2, "|")
	str3 := strings.Join(sl2, ";")
	fmt.Printf("sl2 joined result %s\n", str3)

	str4 := " world"
	str4 = str + str4
	fmt.Println(str4)
}

func mapPractise() {
	for ix, v := range map1 {
		fmt.Println("idx:", ix, "value:", v)
	}

	key1 := "two"
	if v, present := map1[key1]; present {
		fmt.Println(v)
	}

	delete(map1, key1)
	if v, present := map1[key1]; present {
		fmt.Println(v)
	} else {
		fmt.Println("key does not exist")
	}
}

func structPractise() {
	robot1 := new(robot)
	robot1.name = "Kfc443"
	robot1.power = 5
	fmt.Println(robot1)

	robot2 := &robot{"Mlc80", 999}
	fmt.Println(robot2)

	robot3 := newRobot("Ll88", 777)
	fmt.Println(robot3)
}

func newRobot(name string, power int) *robot {
	return &robot{name, power}
}

func interfacePractise() {
	var worker1 worker
	a := newRobot("Tom", 20)
	worker1 = a

	if _, ok := worker1.(*robot); ok {
		fmt.Println("worker is a robot!")
	}

	b := &human{"Lilei", 5}
	worker1 = b
	switch worker1.(type) {
	case *robot:
		fmt.Println("worker is a robot!")
	case *human:
		fmt.Println("worker is a human!")
	default:
		fmt.Println("worker is unknown!")
	}
}

func tcpPractise() {
	port := 8080
	addr := fmt.Sprintf(":%d", port)
	log.Println("addr is ", addr)
	_, err := net.ResolveTCPAddr("tcp", addr)
	if err != nil {
		log.Println("can't resolve addr", addr, err.Error())
	}
}
<|endoftext|>


<commit_before>// Package prompter is utility for easy prompting
package prompter

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strings"

	"github.com/mattn/go-isatty"
	"golang.org/x/crypto/ssh/terminal"
)

// VERSION version of prompter
const VERSION = "0.3.0"

// Prompter is object for prompting
type Prompter struct {
	Message string
	// choices of answer
	Choices    []string
	IgnoreCase bool
	Default    string
	// specify answer pattern by regexp. When both Choices and Regexp are specified, Regexp takes a priority.
	Regexp *regexp.Regexp
	// for passwords and so on.
	NoEcho     bool
	UseDefault bool
	reg        *regexp.Regexp
}

// Prompt displays a prompt and returns answer
func (p *Prompter) Prompt() string {
	fmt.Print(p.msg())
	if p.UseDefault || skip() {
		return p.Default
	}
	input := ""
	if p.NoEcho {
		b, err := terminal.ReadPassword(int(os.Stdin.Fd()))
		if err == nil {
			input = string(b)
		}
		fmt.Print("\n")
	} else {
		scanner := bufio.NewScanner(os.Stdin)
		ok := scanner.Scan()
		if ok {
			input = strings.TrimRight(scanner.Text(), "\r\n")
		}
	}
	if input == "" {
		input = p.Default
	}
	if !p.inputIsValid(input) {
		fmt.Println(p.errorMsg())
		return p.Prompt()
	}
	return input
}

func skip() bool {
	if os.Getenv("GO_PROMPTER_USE_DEFAULT") != "" {
		return true
	}
	return !(isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd())) ||
		!(isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()))
}

func (p *Prompter) msg() string {
	msg := p.Message
	if p.Choices != nil && len(p.Choices) > 0 {
		msg += fmt.Sprintf(" (%s)", strings.Join(p.Choices, "/"))
	}
	if p.Default != "" {
		msg += " [" + p.Default + "]"
	}
	return msg + ": "
}

func (p *Prompter) errorMsg() string {
	if p.Regexp != nil {
		return fmt.Sprintf("# Answer should match /%s/", p.Regexp)
	}
	if p.Choices != nil && len(p.Choices) > 0 {
		if len(p.Choices) == 1 {
			return fmt.Sprintf("# Enter `%s`", p.Choices[0])
		}
		choices := make([]string, len(p.Choices)-1)
		for i, v := range p.Choices[:len(p.Choices)-1] {
			choices[i] = "`" + v + "`"
		}
		return fmt.Sprintf("# Enter %s or `%s`", strings.Join(choices, ", "), p.Choices[len(p.Choices)-1])
	}
	return ""
}

func (p *Prompter) inputIsValid(input string) bool {
	return p.regexp().MatchString(input)
}

var allReg = regexp.MustCompile(`.*`)

func (p *Prompter) regexp() *regexp.Regexp {
	if p.Regexp != nil {
		return p.Regexp
	}
	if p.reg != nil {
		return p.reg
	}
	if p.Choices == nil || len(p.Choices) == 0 {
		p.reg = allReg
		return p.reg
	}

	choices := make([]string, len(p.Choices))
	for i, v := range p.Choices {
		choices[i] = regexp.QuoteMeta(v)
	}
	ignoreReg := ""
	if p.IgnoreCase {
		ignoreReg = "(?i)"
	}
	p.reg = regexp.MustCompile(fmt.Sprintf(`%s\A(?:%s)\z`, ignoreReg, strings.Join(choices, "|")))
	return p.reg
}
<commit_msg>There are also cases using pipes<commit_after>// Package prompter is utility for easy prompting
package prompter

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strings"

	"github.com/mattn/go-isatty"
	"golang.org/x/crypto/ssh/terminal"
)

// VERSION version of prompter
const VERSION = "0.3.0"

// Prompter is object for prompting
type Prompter struct {
	Message string
	// choices of answer
	Choices    []string
	IgnoreCase bool
	Default    string
	// specify answer pattern by regexp. When both Choices and Regexp are specified, Regexp takes a priority.
	Regexp *regexp.Regexp
	// for passwords and so on.
	NoEcho     bool
	UseDefault bool
	reg        *regexp.Regexp
}

// Prompt displays a prompt and returns answer
func (p *Prompter) Prompt() string {
	fmt.Print(p.msg())
	if p.UseDefault || skip() {
		return p.Default
	}
	input := ""
	if p.NoEcho {
		b, err := terminal.ReadPassword(int(os.Stdin.Fd()))
		if err == nil {
			input = string(b)
		}
		fmt.Print("\n")
	} else {
		scanner := bufio.NewScanner(os.Stdin)
		ok := scanner.Scan()
		if ok {
			input = strings.TrimRight(scanner.Text(), "\r\n")
		}
	}
	if input == "" {
		input = p.Default
	}
	if !p.inputIsValid(input) {
		fmt.Println(p.errorMsg())
		return p.Prompt()
	}
	return input
}

func skip() bool {
	if os.Getenv("GO_PROMPTER_USE_DEFAULT") != "" {
		return true
	}
	if isPipe() {
		return os.Getenv("GO_PROMPTER_USE_PIPE") == ""
	}
	return false
}

func isPipe() bool {
	return !(isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd())) ||
		!(isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()))

}

func (p *Prompter) msg() string {
	msg := p.Message
	if p.Choices != nil && len(p.Choices) > 0 {
		msg += fmt.Sprintf(" (%s)", strings.Join(p.Choices, "/"))
	}
	if p.Default != "" {
		msg += " [" + p.Default + "]"
	}
	return msg + ": "
}

func (p *Prompter) errorMsg() string {
	if p.Regexp != nil {
		return fmt.Sprintf("# Answer should match /%s/", p.Regexp)
	}
	if p.Choices != nil && len(p.Choices) > 0 {
		if len(p.Choices) == 1 {
			return fmt.Sprintf("# Enter `%s`", p.Choices[0])
		}
		choices := make([]string, len(p.Choices)-1)
		for i, v := range p.Choices[:len(p.Choices)-1] {
			choices[i] = "`" + v + "`"
		}
		return fmt.Sprintf("# Enter %s or `%s`", strings.Join(choices, ", "), p.Choices[len(p.Choices)-1])
	}
	return ""
}

func (p *Prompter) inputIsValid(input string) bool {
	return p.regexp().MatchString(input)
}

var allReg = regexp.MustCompile(`.*`)

func (p *Prompter) regexp() *regexp.Regexp {
	if p.Regexp != nil {
		return p.Regexp
	}
	if p.reg != nil {
		return p.reg
	}
	if p.Choices == nil || len(p.Choices) == 0 {
		p.reg = allReg
		return p.reg
	}

	choices := make([]string, len(p.Choices))
	for i, v := range p.Choices {
		choices[i] = regexp.QuoteMeta(v)
	}
	ignoreReg := ""
	if p.IgnoreCase {
		ignoreReg = "(?i)"
	}
	p.reg = regexp.MustCompile(fmt.Sprintf(`%s\A(?:%s)\z`, ignoreReg, strings.Join(choices, "|")))
	return p.reg
}
<|endoftext|>