<commit_before>package gorpc

import (
	"bytes"
	"sync"
	"time"

	"github.com/gsdocker/gserrors"
	"github.com/gsdocker/gslogger"
)

// Sink .
type Sink interface {
	Channel
	AddService(dispatcher Dispatcher)
	RemoveService(dispatcher Dispatcher)
	MessageReceived(message *Message) error
}

type _Sink struct {
	gslogger.Log                       // Mixin Log APIs
	sync.RWMutex                       // mutex
	name         string                // name
	timeout      time.Duration         // timeout
	seqID        uint16                // sequence id
	dispatchers  map[uint16]Dispatcher // register dispatchers
	promises     map[uint16]Promise    // rpc promise
	channel      MessageChannel        // channel
	eventLoop    EventLoop             // event loop
}

// NewSink .
func NewSink(name string, eventLoop EventLoop, channel MessageChannel, timeout time.Duration) Sink {
	return &_Sink{
		Log:         gslogger.Get("sink"),
		name:        name,
		timeout:     timeout,
		dispatchers: make(map[uint16]Dispatcher),
		promises:    make(map[uint16]Promise),
		channel:     channel,
		eventLoop:   eventLoop,
	}
}

// Register .
func (sink *_Sink) AddService(dispatcher Dispatcher) {
	sink.Lock()
	defer sink.Unlock()

	sink.dispatchers[dispatcher.ID()] = dispatcher
}

// Unreigster .
func (sink *_Sink) RemoveService(dispatcher Dispatcher) {
	sink.Lock()
	defer sink.Unlock()

	if dispatcher, ok := sink.dispatchers[dispatcher.ID()]; ok && dispatcher == dispatcher {
		delete(sink.dispatchers, dispatcher.ID())
	}
}

func (sink *_Sink) Promise() (Promise, uint16) {

	sink.Lock()
	defer sink.Unlock()

	for {
		seqID := sink.seqID

		sink.seqID++

		_, ok := sink.promises[seqID]

		if ok {
			continue
		}

		promise := NewPromise(sink.eventLoop, sink.timeout, func() {
			sink.Lock()
			defer sink.Unlock()

			delete(sink.promises, seqID)
		})

		sink.promises[seqID] = promise

		return promise, seqID
	}
}

// Send .
func (sink *_Sink) Send(call *Request) (Future, error) {

	promise, id := sink.Promise()

	call.ID = id

	var buff bytes.Buffer

	err := WriteRequest(&buff, call)

	if err != nil {
		promise.Cancel()
		return nil, err
	}

	message := NewMessage()

	message.Code = CodeRequest

	message.Content = buff.Bytes()

	err = sink.channel.SendMessage(message)

	if err != nil {
		promise.Cancel()
		return nil, err
	}

	sink.I("%s send request(%d:%d:%d)", sink.name, call.ID, call.Service, call.Method)

	return promise, nil
}

func (sink *_Sink) dispatchResponse(response *Response) {
	sink.Lock()
	defer sink.Unlock()

	if promise, ok := sink.promises[response.ID]; ok {
		go promise.Notify(response, nil)
		delete(sink.promises, response.ID)
		return
	}

	sink.W("%s unhandle response(%d)(%d) %s", sink.name, response.ID, response.Service, gserrors.Newf(nil, ""))
}

func (sink *_Sink) dispatch(id uint16) (dispatcher Dispatcher, ok bool) {
	sink.RLock()
	defer sink.RUnlock()

	dispatcher, ok = sink.dispatchers[id]

	return
}

func (sink *_Sink) dispatchRequest(message *Message) error {

	request, err := ReadRequest(bytes.NewBuffer(message.Content))

	if err != nil {
		sink.E("[%s] unmarshal request error\n%s", sink.name, err)
		return err
	}

	sink.I("%s received request(%d:%d:%d)", sink.name, request.ID, request.Service, request.Method)

	if dispatcher, ok := sink.dispatch(request.Service); ok {

		response, err := dispatcher.Dispatch(request)

		if err != nil {
			sink.E("dispatch request(%d)(%d:%d) error\n%s", request.ID, request.Service, request.Method, err)
			return nil
		}

		var buff bytes.Buffer

		err = WriteResponse(&buff, response)

		if err != nil {
			sink.E("marshal request(%d)(%d:%d)'s response error\n%s", request.ID, request.Service, request.Method, err)
			return nil
		}

		message.Code = CodeResponse

		message.Content = buff.Bytes()

		sink.channel.SendMessage(message)

		sink.I("%s send response(%d)(%d)", sink.name, response.ID, response.Service)

		return nil
	}

	sink.W("[%s] unhandle request(%d)(%d:%d)", sink.name, request.ID, request.Service, request.Method)

	return nil
}

func (sink *_Sink) MessageReceived(message *Message) error {

	switch message.Code {
	case CodeRequest:

		sink.dispatchRequest(message)

		return nil

	case CodeResponse:

		response, err := ReadResponse(bytes.NewBuffer(message.Content))

		if err != nil {
			sink.E("[%s] unmarshal response error\n%s", sink.name, err)
			return err
		}

		sink.dispatchResponse(response)

		return nil

	default:

		sink.W("[%s] unsupport message(%s)", sink.name, message.Code)

		return nil
	}
}
<commit_msg>update<commit_after>package gorpc

import (
	"bytes"
	"sync"
	"time"

	"github.com/gsdocker/gserrors"
	"github.com/gsdocker/gslogger"
)

// Sink .
type Sink interface {
	Channel
	AddService(dispatcher Dispatcher)
	RemoveService(dispatcher Dispatcher)
	MessageReceived(message *Message) error
}

type _Sink struct {
	gslogger.Log                       // Mixin Log APIs
	sync.RWMutex                       // mutex
	name         string                // name
	timeout      time.Duration         // timeout
	seqID        uint16                // sequence id
	dispatchers  map[uint16]Dispatcher // register dispatchers
	promises     map[uint16]Promise    // rpc promise
	channel      MessageChannel        // channel
	eventLoop    EventLoop             // event loop
}

// NewSink .
func NewSink(name string, eventLoop EventLoop, channel MessageChannel, timeout time.Duration) Sink {
	return &_Sink{
		Log:         gslogger.Get("sink"),
		name:        name,
		timeout:     timeout,
		dispatchers: make(map[uint16]Dispatcher),
		promises:    make(map[uint16]Promise),
		channel:     channel,
		eventLoop:   eventLoop,
	}
}

// Register .
func (sink *_Sink) AddService(dispatcher Dispatcher) {
	sink.Lock()
	defer sink.Unlock()

	sink.dispatchers[dispatcher.ID()] = dispatcher
}

// Unreigster .
func (sink *_Sink) RemoveService(dispatcher Dispatcher) {
	sink.Lock()
	defer sink.Unlock()

	if dispatcher, ok := sink.dispatchers[dispatcher.ID()]; ok && dispatcher == dispatcher {
		delete(sink.dispatchers, dispatcher.ID())
	}
}

func (sink *_Sink) Promise() (Promise, uint16) {

	sink.Lock()
	defer sink.Unlock()

	for {
		seqID := sink.seqID

		sink.seqID++

		_, ok := sink.promises[seqID]

		if ok {
			continue
		}

		promise := NewPromise(sink.eventLoop, sink.timeout, func() {
			sink.Lock()
			defer sink.Unlock()

			delete(sink.promises, seqID)
		})

		sink.promises[seqID] = promise

		return promise, seqID
	}
}

// Send .
func (sink *_Sink) Send(call *Request) (Future, error) {

	promise, id := sink.Promise()

	call.ID = id

	var buff bytes.Buffer

	err := WriteRequest(&buff, call)

	if err != nil {
		promise.Cancel()
		return nil, err
	}

	message := NewMessage()

	message.Code = CodeRequest

	message.Content = buff.Bytes()

	err = sink.channel.SendMessage(message)

	if err != nil {
		promise.Cancel()
		return nil, err
	}

	sink.V("%s send request(%d:%d:%d)", sink.name, call.ID, call.Service, call.Method)

	return promise, nil
}

func (sink *_Sink) dispatchResponse(response *Response) {
	sink.Lock()
	defer sink.Unlock()

	if promise, ok := sink.promises[response.ID]; ok {
		go promise.Notify(response, nil)
		delete(sink.promises, response.ID)
		return
	}

	sink.W("%s unhandle response(%d)(%d) %s", sink.name, response.ID, response.Service, gserrors.Newf(nil, ""))
}

func (sink *_Sink) dispatch(id uint16) (dispatcher Dispatcher, ok bool) {
	sink.RLock()
	defer sink.RUnlock()

	dispatcher, ok = sink.dispatchers[id]

	return
}

func (sink *_Sink) dispatchRequest(message *Message) error {

	request, err := ReadRequest(bytes.NewBuffer(message.Content))

	if err != nil {
		sink.E("[%s] unmarshal request error\n%s", sink.name, err)
		return err
	}

	sink.V("%s received request(%d:%d:%d)", sink.name, request.ID, request.Service, request.Method)

	if dispatcher, ok := sink.dispatch(request.Service); ok {

		response, err := dispatcher.Dispatch(request)

		if err != nil {
			sink.E("dispatch request(%d)(%d:%d) error\n%s", request.ID, request.Service, request.Method, err)
			return nil
		}

		var buff bytes.Buffer

		err = WriteResponse(&buff, response)

		if err != nil {
			sink.E("marshal request(%d)(%d:%d)'s response error\n%s", request.ID, request.Service, request.Method, err)
			return nil
		}

		message.Code = CodeResponse

		message.Content = buff.Bytes()

		sink.channel.SendMessage(message)

		sink.V("%s send response(%d)(%d)", sink.name, response.ID, response.Service)

		return nil
	}

	sink.W("[%s] unhandle request(%d)(%d:%d)", sink.name, request.ID, request.Service, request.Method)

	return nil
}

func (sink *_Sink) MessageReceived(message *Message) error {

	switch message.Code {
	case CodeRequest:

		sink.dispatchRequest(message)

		return nil

	case CodeResponse:

		response, err := ReadResponse(bytes.NewBuffer(message.Content))

		if err != nil {
			sink.E("[%s] unmarshal response error\n%s", sink.name, err)
			return err
		}

		sink.dispatchResponse(response)

		return nil

	default:

		sink.W("[%s] unsupport message(%s)", sink.name, message.Code)

		return nil
	}
}
<|endoftext|>


<commit_before>package flux

import (
	"io"
	slog "log"
	"sync/atomic"

	"github.com/op/go-logging"
)

type (

	//HalfStackable defines a stackable function type that can return a value
	HalfStackable func(interface{})

	//Stackable defines a stackable function type that can return a value
	Stackable func(interface{}, Stacks) interface{}

	//Stacks provides the finite definition of function stacks
	Stacks interface {
		Stack(Stackable, bool) Stacks
		Listen(HalfStackable) Stacks
		Unstack()

		//Isolate applies to this stack only and does not propagate the value to other stacks
		Isolate(interface{}) interface{}

		//Identity returns the value apply to it as the return value
		Identity(interface{}) interface{}

		//Call runs the value, returning the return value of just this particular stacks return value
		Call(interface{}) interface{}

		//Apply applies the value, returning the values of either this stack or the child stacks if any exists
		Apply(interface{}) interface{}

		//Lift lifts this value up the root stack for use with the root .Apply() function(allows you to call a root .Apply() method from anylevel of the stack)
		Lift(interface{}) interface{}

		//LiftApply calls the stack from bottom up and takes the result from a lower stack to apply to its parent stack
		LiftApply(interface{}) interface{}
		Levitate(interface{}) interface{}

		getWrap() *StackWrap
		Close() error
		LockClose(Stacks)
	}

	//StackWrap provides a single-layer two function binder
	StackWrap struct {
		Fn      Stackable
		next    *StackWrap
		owner   Stacks
		closefx func()
	}

	//Stack is the concrete definition of Stacks
	Stack struct {
		wrap   *StackWrap
		root   Stacks
		active int64
	}

	//StackStreamers provides a streaming function for stacks member rules
	StackStreamers interface {
		Stacks
		StreamWriter(io.Writer) Stacks
		Write([]byte) (int, error)
		Read([]byte) (int, error)
		Closed() Stacks
	}

	//StackStream is the concrete implementation for stacks
	StackStream struct {
		Stacks
		closeNotifier Stacks
	}

	//Reports provides a abstraction of report
	Reports struct {
		Tag  string
		Meta map[string]interface{}
	}

	//StackReport provides a internal bank of reports
	StackReport struct {
		stacks chan *Reports
		ended  int64
	}
)

var (
	//StackableIdentity provides an identity function for stacks
	StackableIdentity = func(b interface{}, _ Stacks) interface{} {
		return b
	}
)

//ReportCard returns a new StackReport instance, generally ensure its a good max so you can get reports without over-filling the stack,if the stack is full then old reports would be discard
func ReportCard(max int) *StackReport {
	return &StackReport{
		stacks: make(chan *Reports, max),
	}
}

//Checkout returns a Stack which gets filled with the current and possible future reports
func (r *StackReport) Checkout() StackStreamers {
	cs := NewIdentityStream()
	GoDefer("CheckoutReport", func() {
		for {

			state := atomic.LoadInt64(&r.ended)

			if state > 0 {
				break
			}

			select {
			case v, ok := <-r.stacks:
				if !ok {
					return
				}
				cs.Call(v)
			}
		}
	})
	return cs
}

//Report adds a new report to the reportstack
func (r *StackReport) Report(tag string, meta map[string]interface{}) {
	state := atomic.LoadInt64(&r.ended)

	if state > 0 {
		return
	}

	curcap := cap(r.stacks)
	curlen := len(r.stacks)

	if curlen >= curcap {
		GoDefer("DiscardTopReport", func() {
			<-r.stacks
		})
	}

	r.stacks <- &Reports{tag, meta}
}

//Close ends the report card operations
func (r *StackReport) Close() {
	state := atomic.LoadInt64(&r.ended)
	if state > 0 {
		return
	}

	atomic.StoreInt64(&r.ended, 1)
	close(r.stacks)
}

//NewIdentityStream  returns new StackStream
func NewIdentityStream() StackStreamers {
	return NewStackStream(StackableIdentity)
}

//StreamReader streams from a reader,hence all values are replaced by the data in the io.Reader
func StreamReader(w io.Reader) (s StackStreamers) {
	s = NewStackStream(StackableIdentity)
	go func() {
		_, _ = io.Copy(s, w)
	}()
	return
}

//Read reads into a byte but its empty
func (s *StackStream) Read(bu []byte) (int, error) {
	return 0, io.ErrNoProgress
}

//Write writes into the stream
func (s *StackStream) Write(bu []byte) (int, error) {
	s.Call(bu)
	return len(bu), nil
}

//StreamWriter streams to a writer
func (s *StackStream) StreamWriter(w io.Writer) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		buff, ok := data.([]byte)

		if !ok {

			str, ok := data.(string)

			if ok {
				_, _ = w.Write([]byte(str))
			}

		}
		_, _ = w.Write(buff)
		return data
	}, true)
}

//Closed returns a stack that is emitted when closed
func (s *StackStream) Closed() Stacks {
	return s.closeNotifier
}

//Close ends this stacks connections
func (s *StackStream) Close() error {
	defer s.closeNotifier.Close()
	s.closeNotifier.Call(true)
	s.Stacks.Close()
	return nil
}

//NewStackStream returns a new stackstream
func NewStackStream(mx Stackable) StackStreamers {
	return &StackStream{
		Stacks:        NewStack(mx),
		closeNotifier: NewStack(StackableIdentity),
	}
}

//Close destroys the stackwrap
func (s *StackWrap) Close() {
	if s.next != nil {
		if s.next.owner != nil {
			s.next.owner.Close()
		}
	}
	s.Fn = nil
	s.owner = nil
	if s.closefx != nil {
		defer func() { s.closefx = nil }()
		s.closefx()
	}
}

//Unwrap unwraps a Stackwrap for release
func (s *StackWrap) Unwrap() *StackWrap {
	nx := s.next
	s.next = nil
	return nx
}

//Rewrap wraps a new Stackwrap aw next
func (s *StackWrap) Rewrap(sc *StackWrap) *StackWrap {
	nx := s.Unwrap()
	s.next = sc
	return nx
}

//NewStackWrap returns a new Stackwrap
func NewStackWrap(fn Stackable, own Stacks, fx func()) *StackWrap {
	return &StackWrap{Fn: fn, owner: own, next: nil, closefx: fx}
}

//NewStack returns a new stack
func NewStack(fn Stackable) (s *Stack) {
	s = &Stack{
		active: 1,
	}

	s.wrap = NewStackWrap(fn, s, nil)
	return
}

//Isolate applies to this stack only and does not propagate the value to other stacks
func (s *Stack) Isolate(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
	}
	return res
}

//Identity sends a data into the stack and returns the value supplied,like apply a matrix op V * I = V
func (s *Stack) Identity(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	// res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		_ = s.wrap.Fn(b, s)
		if s.wrap != nil {
			if s.wrap.next != nil {
				if s.wrap.next.owner != nil {
					_ = s.wrap.next.owner.Identity(b)
				}
			}
		}
	}

	return b
}

//Call runs the value returning the return value of just this particular stacks return value
func (s *Stack) Call(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap != nil {
			if s.wrap.next != nil {
				if s.wrap.next.owner != nil {
					_ = s.wrap.next.owner.Call(res)
				}
			}
		}
	}
	return res
}

//Apply sends a data into the stack and returns this stack
//returned value
func (s *Stack) Apply(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap != nil {
			if s.wrap.next != nil {
				if s.wrap.next.owner != nil {
					return s.wrap.next.owner.Apply(res)
				}
			}
		}
	}
	return res
}

//Lift allows the passing of a value to the root of a tree before executing an emit downwards
func (s *Stack) Lift(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	if s.root != nil {
		return s.root.Lift(b)
	}

	return s.Apply(b)
}

//Levitate takes a value,mutates it then passes up to the root, moving from bottom-up and returns the roots returned value
func (s *Stack) Levitate(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := s.wrap.Fn(b, s)

	if s.root != nil {
		s.root.LiftApply(res)
		// return s.root.LiftApply(res)
	}

	return res
}

//LiftApply takes a value,mutates it then pass that to the root. moving from bottom-to-top
func (s *Stack) LiftApply(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := s.wrap.Fn(b, s)

	if s.root != nil {
		return s.root.Levitate(res)
	}

	return res
}

//Close destroys the stack and any other chain it has
func (s *Stack) Close() error {
	if s.wrap == nil {
		return nil
	}

	defer func() { s.wrap = nil }()
	s.Unstack()
	s.wrap.Close()
	return nil
}

//Unstack disables and nullifies this stack
func (s *Stack) Unstack() {
	if s.wrap == nil || s.root == nil {
		return
	}

	root := s.root
	nxt := s.wrap.next

	atomic.StoreInt64(&s.active, 0)
	root.getWrap().Rewrap(nxt)
	s.root = nil
}

//getWrap returns the stacks wrapper
func (s *Stack) getWrap() *StackWrap {
	return s.wrap
}

//Listen builds a new stack from this previous stack
func (s *Stack) Listen(fn HalfStackable) Stacks {
	return s.Stack(func(b interface{}, _ Stacks) interface{} {
		fn(b)
		return b
	}, true)
}

//LockClose locks the stacks to the close of this
func (s *Stack) LockClose(m Stacks) {
	cx := s.getWrap().closefx
	s.getWrap().closefx = func() {
		m.Close()
		if cx != nil {
			cx()
		}
	}
}

//Stack builds a new stack from this previous stack, the connectClose defines whether you want the new Stack closed when its parent is closed,if false then we dont close it when the root closes
func (s *Stack) Stack(fn Stackable, connectClose bool) Stacks {
	if s.wrap == nil {
		return nil
	}

	if s.wrap.next != nil {
		if s.wrap.next.owner != nil {
			return s.wrap.next.owner.Stack(fn, connectClose)
		}
	}

	m := NewStack(fn)
	m.root = s

	s.wrap.next = m.wrap

	if connectClose {
		s.LockClose(m)
	}

	return m
}

//LogStack takes a stack and logs all input coming from it
func LogStack(s Stacks) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		log.Info("LogStack: %+s", data)
		return data
	}, true)
}

//LogHeader takes a stack and logs all input from it
func LogHeader(s Stacks, header string) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		log.Info(header, data)
		return data
	}, true)
}

//LogStackWith logs all input using a custom logger
func LogStackWith(s Stacks, l *slog.Logger) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		l.Printf("LogStack: %+s", data)
		return data
	}, true)
}

//CustomLogStackWith logs all input using a custom logger
func CustomLogStackWith(s Stacks, l *logging.Logger) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		l.Info("LogStack: %+s", data)
		return data
	}, true)
}
<commit_msg>fix levitate and lifeapply wrong calls<commit_after>package flux

import (
	"io"
	slog "log"
	"sync/atomic"

	"github.com/op/go-logging"
)

type (

	//HalfStackable defines a stackable function type that can return a value
	HalfStackable func(interface{})

	//Stackable defines a stackable function type that can return a value
	Stackable func(interface{}, Stacks) interface{}

	//Stacks provides the finite definition of function stacks
	Stacks interface {
		Stack(Stackable, bool) Stacks
		Listen(HalfStackable) Stacks
		Unstack()

		//Isolate applies to this stack only and does not propagate the value to other stacks
		Isolate(interface{}) interface{}

		//Identity returns the value apply to it as the return value
		Identity(interface{}) interface{}

		//Call runs the value, returning the return value of just this particular stacks return value
		Call(interface{}) interface{}

		//Apply applies the value, returning the values of either this stack or the child stacks if any exists
		Apply(interface{}) interface{}

		//Lift lifts this value up the root stack for use with the root .Apply() function(allows you to call a root .Apply() method from anylevel of the stack)
		Lift(interface{}) interface{}

		//LiftApply calls the stack from bottom up and takes the result from a lower stack to apply to its parent stack
		LiftApply(interface{}) interface{}
		Levitate(interface{}) interface{}

		getWrap() *StackWrap
		Close() error
		LockClose(Stacks)
	}

	//StackWrap provides a single-layer two function binder
	StackWrap struct {
		Fn      Stackable
		next    *StackWrap
		owner   Stacks
		closefx func()
	}

	//Stack is the concrete definition of Stacks
	Stack struct {
		wrap   *StackWrap
		root   Stacks
		active int64
	}

	//StackStreamers provides a streaming function for stacks member rules
	StackStreamers interface {
		Stacks
		StreamWriter(io.Writer) Stacks
		Write([]byte) (int, error)
		Read([]byte) (int, error)
		Closed() Stacks
	}

	//StackStream is the concrete implementation for stacks
	StackStream struct {
		Stacks
		closeNotifier Stacks
	}

	//Reports provides a abstraction of report
	Reports struct {
		Tag  string
		Meta map[string]interface{}
	}

	//StackReport provides a internal bank of reports
	StackReport struct {
		stacks chan *Reports
		ended  int64
	}
)

var (
	//StackableIdentity provides an identity function for stacks
	StackableIdentity = func(b interface{}, _ Stacks) interface{} {
		return b
	}
)

//ReportCard returns a new StackReport instance, generally ensure its a good max so you can get reports without over-filling the stack,if the stack is full then old reports would be discard
func ReportCard(max int) *StackReport {
	return &StackReport{
		stacks: make(chan *Reports, max),
	}
}

//Checkout returns a Stack which gets filled with the current and possible future reports
func (r *StackReport) Checkout() StackStreamers {
	cs := NewIdentityStream()
	GoDefer("CheckoutReport", func() {
		for {

			state := atomic.LoadInt64(&r.ended)

			if state > 0 {
				break
			}

			select {
			case v, ok := <-r.stacks:
				if !ok {
					return
				}
				cs.Call(v)
			}
		}
	})
	return cs
}

//Report adds a new report to the reportstack
func (r *StackReport) Report(tag string, meta map[string]interface{}) {
	state := atomic.LoadInt64(&r.ended)

	if state > 0 {
		return
	}

	curcap := cap(r.stacks)
	curlen := len(r.stacks)

	if curlen >= curcap {
		GoDefer("DiscardTopReport", func() {
			<-r.stacks
		})
	}

	r.stacks <- &Reports{tag, meta}
}

//Close ends the report card operations
func (r *StackReport) Close() {
	state := atomic.LoadInt64(&r.ended)
	if state > 0 {
		return
	}

	atomic.StoreInt64(&r.ended, 1)
	close(r.stacks)
}

//NewIdentityStream  returns new StackStream
func NewIdentityStream() StackStreamers {
	return NewStackStream(StackableIdentity)
}

//StreamReader streams from a reader,hence all values are replaced by the data in the io.Reader
func StreamReader(w io.Reader) (s StackStreamers) {
	s = NewStackStream(StackableIdentity)
	go func() {
		_, _ = io.Copy(s, w)
	}()
	return
}

//Read reads into a byte but its empty
func (s *StackStream) Read(bu []byte) (int, error) {
	return 0, io.ErrNoProgress
}

//Write writes into the stream
func (s *StackStream) Write(bu []byte) (int, error) {
	s.Call(bu)
	return len(bu), nil
}

//StreamWriter streams to a writer
func (s *StackStream) StreamWriter(w io.Writer) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		buff, ok := data.([]byte)

		if !ok {

			str, ok := data.(string)

			if ok {
				_, _ = w.Write([]byte(str))
			}

		}
		_, _ = w.Write(buff)
		return data
	}, true)
}

//Closed returns a stack that is emitted when closed
func (s *StackStream) Closed() Stacks {
	return s.closeNotifier
}

//Close ends this stacks connections
func (s *StackStream) Close() error {
	defer s.closeNotifier.Close()
	s.closeNotifier.Call(true)
	s.Stacks.Close()
	return nil
}

//NewStackStream returns a new stackstream
func NewStackStream(mx Stackable) StackStreamers {
	return &StackStream{
		Stacks:        NewStack(mx),
		closeNotifier: NewStack(StackableIdentity),
	}
}

//Close destroys the stackwrap
func (s *StackWrap) Close() {
	if s.next != nil {
		if s.next.owner != nil {
			s.next.owner.Close()
		}
	}
	s.Fn = nil
	s.owner = nil
	if s.closefx != nil {
		defer func() { s.closefx = nil }()
		s.closefx()
	}
}

//Unwrap unwraps a Stackwrap for release
func (s *StackWrap) Unwrap() *StackWrap {
	nx := s.next
	s.next = nil
	return nx
}

//Rewrap wraps a new Stackwrap aw next
func (s *StackWrap) Rewrap(sc *StackWrap) *StackWrap {
	nx := s.Unwrap()
	s.next = sc
	return nx
}

//NewStackWrap returns a new Stackwrap
func NewStackWrap(fn Stackable, own Stacks, fx func()) *StackWrap {
	return &StackWrap{Fn: fn, owner: own, next: nil, closefx: fx}
}

//NewStack returns a new stack
func NewStack(fn Stackable) (s *Stack) {
	s = &Stack{
		active: 1,
	}

	s.wrap = NewStackWrap(fn, s, nil)
	return
}

//Isolate applies to this stack only and does not propagate the value to other stacks
func (s *Stack) Isolate(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
	}
	return res
}

//Identity sends a data into the stack and returns the value supplied,like apply a matrix op V * I = V
func (s *Stack) Identity(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	// res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		_ = s.wrap.Fn(b, s)
		if s.wrap != nil {
			if s.wrap.next != nil {
				if s.wrap.next.owner != nil {
					_ = s.wrap.next.owner.Identity(b)
				}
			}
		}
	}

	return b
}

//Call runs the value returning the return value of just this particular stacks return value
func (s *Stack) Call(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap != nil {
			if s.wrap.next != nil {
				if s.wrap.next.owner != nil {
					_ = s.wrap.next.owner.Call(res)
				}
			}
		}
	}
	return res
}

//Apply sends a data into the stack and returns this stack
//returned value
func (s *Stack) Apply(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := b
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap != nil {
			if s.wrap.next != nil {
				if s.wrap.next.owner != nil {
					return s.wrap.next.owner.Apply(res)
				}
			}
		}
	}
	return res
}

//Lift allows the passing of a value to the root of a tree before executing an emit downwards
func (s *Stack) Lift(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	if s.root != nil {
		return s.root.Lift(b)
	}

	return s.Apply(b)
}

//Levitate takes a value,mutates it then passes up to the root, moving from bottom-up and returns the roots returned value
func (s *Stack) Levitate(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := s.wrap.Fn(b, s)

	if s.root != nil {
		s.root.Levitate(res)
		// return s.root.LiftApply(res)
	}

	return res
}

//LiftApply takes a value,mutates it then pass that to the root. moving from bottom-to-top
func (s *Stack) LiftApply(b interface{}) interface{} {
	if b == nil {
		return nil
	}
	if s.wrap == nil {
		return nil
	}

	res := s.wrap.Fn(b, s)

	if s.root != nil {
		return s.root.LiftApply(res)
	}

	return res
}

//Close destroys the stack and any other chain it has
func (s *Stack) Close() error {
	if s.wrap == nil {
		return nil
	}

	defer func() { s.wrap = nil }()
	s.Unstack()
	s.wrap.Close()
	return nil
}

//Unstack disables and nullifies this stack
func (s *Stack) Unstack() {
	if s.wrap == nil || s.root == nil {
		return
	}

	root := s.root
	nxt := s.wrap.next

	atomic.StoreInt64(&s.active, 0)
	root.getWrap().Rewrap(nxt)
	s.root = nil
}

//getWrap returns the stacks wrapper
func (s *Stack) getWrap() *StackWrap {
	return s.wrap
}

//Listen builds a new stack from this previous stack
func (s *Stack) Listen(fn HalfStackable) Stacks {
	return s.Stack(func(b interface{}, _ Stacks) interface{} {
		fn(b)
		return b
	}, true)
}

//LockClose locks the stacks to the close of this
func (s *Stack) LockClose(m Stacks) {
	cx := s.getWrap().closefx
	s.getWrap().closefx = func() {
		m.Close()
		if cx != nil {
			cx()
		}
	}
}

//Stack builds a new stack from this previous stack, the connectClose defines whether you want the new Stack closed when its parent is closed,if false then we dont close it when the root closes
func (s *Stack) Stack(fn Stackable, connectClose bool) Stacks {
	if s.wrap == nil {
		return nil
	}

	if s.wrap.next != nil {
		if s.wrap.next.owner != nil {
			return s.wrap.next.owner.Stack(fn, connectClose)
		}
	}

	m := NewStack(fn)
	m.root = s

	s.wrap.next = m.wrap

	if connectClose {
		s.LockClose(m)
	}

	return m
}

//LogStack takes a stack and logs all input coming from it
func LogStack(s Stacks) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		log.Info("LogStack: %+s", data)
		return data
	}, true)
}

//LogHeader takes a stack and logs all input from it
func LogHeader(s Stacks, header string) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		log.Info(header, data)
		return data
	}, true)
}

//LogStackWith logs all input using a custom logger
func LogStackWith(s Stacks, l *slog.Logger) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		l.Printf("LogStack: %+s", data)
		return data
	}, true)
}

//CustomLogStackWith logs all input using a custom logger
func CustomLogStackWith(s Stacks, l *logging.Logger) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		l.Info("LogStack: %+s", data)
		return data
	}, true)
}
<|endoftext|>


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

package main

import (
	"context"
	"flag"
	"image"
	"image/color"
	"log"

	"github.com/zagrodzki/goscope/compat"
	"github.com/zagrodzki/goscope/dummy"
	"github.com/zagrodzki/goscope/gui"
	"github.com/zagrodzki/goscope/scope"
	"github.com/zagrodzki/goscope/triggers"
	"golang.org/x/exp/shiny/driver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/time/rate"
)

const (
	screenWidth      = 1200
	screenHeight     = 600
	refreshRateLimit = 25
)

var (
	hasTrigger = flag.Bool("enable_trigger", true, "When true, a trigger is configured on the device")
	useChan    = flag.String("channel", "sin", "one of the channels of dummy device: zero,random,sin,triangle,square")
)

func main() {
	flag.Parse()
	dev, _ := dummy.Open(*useChan)
	rec := &compat.Recorder{TB: scope.Millisecond}
	dev.Attach(rec)
	dev.Start()
	defer dev.Stop()

	zas := make(map[scope.ChanID]gui.TraceParams)
	cols := make(map[scope.ChanID]color.RGBA)
	for _, id := range dev.Channels() {
		zas[id] = gui.TraceParams{Zero: 0.5, PerDiv: 2, Interp: gui.SincInterpolator}
		cols[id] = color.RGBA{0, 0, 255, 255}
	}

	driver.Main(func(s screen.Screen) {
		w, err := s.NewWindow(&screen.NewWindowOptions{Width: screenWidth, Height: screenHeight})
		if err != nil {
			log.Fatalf("NewWindow: %v", err)
		}
		defer w.Release()
		stop := make(chan struct{})
		go processEvents(w, stop)

		b, err := s.NewBuffer(image.Point{screenWidth, screenHeight})
		if err != nil {
			log.Fatalf("NewBuffer(): %v", err)
		}
		defer b.Release()
		limiter := rate.NewLimiter(rate.Limit(refreshRateLimit), 1)
		var in <-chan scope.Data
		if *hasTrigger {
			newCh := make(chan scope.Data, 10)
			tr := triggers.New(rec.Data, newCh)
			in = newCh
			tr.TimeBase(scope.Millisecond)
			tr.Source(scope.ChanID(*useChan))
			tr.Edge(triggers.Falling)
			tr.Level(-0.9)
		} else {
			in = rec.Data
		}
		for {
			select {
			case <-stop:
				return
			default:
			}
			limiter.Wait(context.Background())
			get := <-in
			p := gui.Plot{b.RGBA()}
			for i := 0; i < len(p.Pix); i++ {
				p.Pix[i] = 255
			}
			p.DrawAll(get.Channels, zas, cols)
			w.Upload(image.Point{0, 0}, b, b.Bounds())
			w.Publish()
		}
	})
}
<commit_msg>Use the new trigger in dummy_screen<commit_after>//  Copyright 2016 The goscope Authors
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package main

import (
	"context"
	"flag"
	"image"
	"image/color"
	"log"

	"github.com/zagrodzki/goscope/compat"
	"github.com/zagrodzki/goscope/dummy"
	"github.com/zagrodzki/goscope/gui"
	"github.com/zagrodzki/goscope/scope"
	"github.com/zagrodzki/goscope/triggers"
	"golang.org/x/exp/shiny/driver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/time/rate"
)

const (
	screenWidth      = 1200
	screenHeight     = 600
	refreshRateLimit = 25
)

var (
	triggerSource = flag.String("trigger_source", "", "Name of the channel to use as a trigger source")
	useChan       = flag.String("channel", "sin", "one of the channels of dummy device: zero,random,sin,triangle,square")
)

func main() {
	flag.Parse()
	dev, _ := dummy.Open(*useChan)
	rec := &compat.Recorder{TB: scope.Second}

	tr := triggers.New(rec)
	tr.Source(scope.ChanID(*triggerSource))
	tr.Edge(triggers.Falling)
	tr.Level(-0.9)

	dev.Attach(tr)
	dev.Start()
	defer dev.Stop()

	zas := make(map[scope.ChanID]gui.TraceParams)
	cols := make(map[scope.ChanID]color.RGBA)
	for _, id := range dev.Channels() {
		zas[id] = gui.TraceParams{Zero: 0.5, PerDiv: 2, Interp: gui.SincInterpolator}
		cols[id] = color.RGBA{0, 0, 255, 255}
	}

	driver.Main(func(s screen.Screen) {
		w, err := s.NewWindow(&screen.NewWindowOptions{Width: screenWidth, Height: screenHeight})
		if err != nil {
			log.Fatalf("NewWindow: %v", err)
		}
		defer w.Release()
		stop := make(chan struct{})
		go processEvents(w, stop)

		b, err := s.NewBuffer(image.Point{screenWidth, screenHeight})
		if err != nil {
			log.Fatalf("NewBuffer(): %v", err)
		}
		defer b.Release()
		limiter := rate.NewLimiter(rate.Limit(refreshRateLimit), 1)
		in := rec.Data
		for {
			select {
			case <-stop:
				return
			default:
			}
			limiter.Wait(context.Background())
			get := <-in
			p := gui.Plot{b.RGBA()}
			for i := 0; i < len(p.Pix); i++ {
				p.Pix[i] = 255
			}
			p.DrawAll(get.Channels, zas, cols)
			w.Upload(image.Point{0, 0}, b, b.Bounds())
			w.Publish()
		}
	})
}
<|endoftext|>


<commit_before>/*

 Package variant provides some (well, at the time of this writing)
 useful implementations of the expvar.Var interface (which is just a
 Stringer).

*/
package variant

import (
	"container/ring"
	"expvar"
	"fmt"
	"math"
	"sort"
	"sync"
)

// represents a size bounded simple moving average
// it is thread/goroutine safe
type SimpleMovingStat struct {
	size      int
	mutex     *sync.Mutex
	values    *ring.Ring
	calculate func(*SimpleMovingStat) float64
}

// Create a new simple moving median expvar.Var. It will be
// published under `name` and maintain `size` values for
// calculating the median.
//
// An empty name will cause it to not be published
//
// This is just a convenience helper for a SimpleMovingPercentile
func NewSimpleMovingMedian(name string, size int) *SimpleMovingStat {
	return NewSimpleMovingPercentile(name, 0.50, size)

}

// Create a new simple moving percentile expvar.Var. It will be
// published under `name` and maintain `size` values for
// calculating the percentile.
//
// percentile must be between 0 and 1
//
// An empty name will cause it to not be published
func NewSimpleMovingPercentile(name string, percentile float64, size int) *SimpleMovingStat {
	sm := new(SimpleMovingStat)
	sm.size = size
	sm.mutex = new(sync.Mutex)
	sm.values = ring.New(size)

	sm.calculate = func(s *SimpleMovingStat) float64 {
		ary := make([]float64, 0)
		s.values.Do(func(val interface{}) {
			if val != nil {
				ary = append(ary, val.(float64))
			}
		})
		length := len(ary)
		if length == 0 {
			return 0.0
		}
		sort.Float64s(ary)
		mid := int(float64(len(ary)) * percentile)
		return ary[mid]
	}

	if name != "" {
		expvar.Publish(name, sm)
	}
	return sm

}

// Create a new simple moving average expvar.Var. It will be
// published under `name` and maintain `size` values for
// calculating the average.
//
// An empty name will cause it to not be published
func NewSimpleMovingAverage(name string, size int) *SimpleMovingStat {
	sma := new(SimpleMovingStat)
	sma.size = size
	sma.mutex = new(sync.Mutex)
	sma.values = ring.New(size)

	sma.calculate = func(s *SimpleMovingStat) float64 {
		var sum float64 = 0.0
		var cnt int = 0

		s.values.Do(func(val interface{}) {
			if val != nil {
				cnt++
				sum = sum + val.(float64)
			}
		})
		return sum / float64(cnt)
	}

	if name != "" {
		expvar.Publish(name, sma)
	}
	return sma
}

// display the value as a string
func (s *SimpleMovingStat) String() string {
	v := s.Value()
	if math.IsNaN(v) {
		return "NaN"
	}
	if math.IsInf(v, 1) {
		return "+Infinity"
	}
	if math.IsInf(v, -1) {
		return "-Infinity"
	}
	return fmt.Sprintf("%f", s.Value())
}

// Append a new value to the stat
func (s *SimpleMovingStat) Update(val float64) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	s.values.Value = val
	s.values = s.values.Next()
}

// obtain the current value
func (s *SimpleMovingStat) Value() float64 {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.calculate(s)
}
<commit_msg>quite it<commit_after>/*

 Package variant provides some (well, at the time of this writing)
 useful implementations of the expvar.Var interface (which is just a
 Stringer).

*/
package variant

import (
	"container/ring"
	"expvar"
	"fmt"
	"math"
	"sort"
	"sync"
)

// represents a size bounded simple moving average
// it is thread/goroutine safe
type SimpleMovingStat struct {
	size      int
	mutex     *sync.Mutex
	values    *ring.Ring
	calculate func(*SimpleMovingStat) float64
}

// Create a new simple moving median expvar.Var. It will be
// published under `name` and maintain `size` values for
// calculating the median.
//
// An empty name will cause it to not be published
//
// This is just a convenience helper for a SimpleMovingPercentile
func NewSimpleMovingMedian(name string, size int) *SimpleMovingStat {
	return NewSimpleMovingPercentile(name, 0.50, size)

}

// Create a new simple moving percentile expvar.Var. It will be
// published under `name` and maintain `size` values for
// calculating the percentile.
//
// percentile must be between 0 and 1
//
// An empty name will cause it to not be published
func NewSimpleMovingPercentile(name string, percentile float64, size int) *SimpleMovingStat {
	sm := new(SimpleMovingStat)
	sm.size = size
	sm.mutex = new(sync.Mutex)
	sm.values = ring.New(size)

	sm.calculate = func(s *SimpleMovingStat) float64 {
		ary := make([]float64, 0)
		s.values.Do(func(val interface{}) {
			if val != nil {
				ary = append(ary, val.(float64))
			}
		})
		length := len(ary)
		if length == 0 {
			return 0.0
		}
		sort.Float64s(ary)
		mid := int(float64(len(ary)) * percentile)
		return ary[mid]
	}

	if name != "" {
		expvar.Publish(name, sm)
	}
	return sm

}

// Create a new simple moving average expvar.Var. It will be
// published under `name` and maintain `size` values for
// calculating the average.
//
// An empty name will cause it to not be published
func NewSimpleMovingAverage(name string, size int) *SimpleMovingStat {
	sma := new(SimpleMovingStat)
	sma.size = size
	sma.mutex = new(sync.Mutex)
	sma.values = ring.New(size)

	sma.calculate = func(s *SimpleMovingStat) float64 {
		var sum float64 = 0.0
		var cnt int = 0

		s.values.Do(func(val interface{}) {
			if val != nil {
				cnt++
				sum = sum + val.(float64)
			}
		})
		return sum / float64(cnt)
	}

	if name != "" {
		expvar.Publish(name, sma)
	}
	return sma
}

// display the value as a string
func (s *SimpleMovingStat) String() string {
	v := s.Value()
	if math.IsNaN(v) {
		return `"NaN"`
	}
	if math.IsInf(v, 1) {
		return `"+Infinity"`
	}
	if math.IsInf(v, -1) {
		return `"-Infinity"`
	}
	return fmt.Sprintf("%f", s.Value())
}

// Append a new value to the stat
func (s *SimpleMovingStat) Update(val float64) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	s.values.Value = val
	s.values = s.values.Next()
}

// obtain the current value
func (s *SimpleMovingStat) Value() float64 {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.calculate(s)
}
<|endoftext|>


<commit_before>// Copyright 2016 Stratumn SAS. All rights reserved.
// Use of this source code is governed by the license
// that can be found in the LICENSE file.

package batchfossilizer

import (
	"encoding/json"
	"fmt"
	"reflect"
	"testing"
	"time"

	"github.com/stratumn/go/fossilizer"
	"github.com/stratumn/go/testutil"
	"github.com/stratumn/go/types"
	"github.com/stratumn/goprivate/merkle"
)

type fossilizeTest struct {
	data       []byte
	meta       []byte
	path       merkle.Path
	sleep      time.Duration
	fossilized bool
}

func testFossilizeMultiple(t *testing.T, a *Fossilizer, tests []fossilizeTest, start bool, fossilize bool) {
	rc := make(chan *fossilizer.Result)
	a.AddResultChan(rc)

	if start {
		go func() {
			if err := a.Start(); err != nil {
				t.Error(err)
			}
		}()
		defer func() {
			if err := a.Stop(); err != nil {
				t.Error(err)
			}
			close(rc)
		}()
	}

	if fossilize {
		for _, test := range tests {
			if err := a.Fossilize(test.data, test.meta); err != nil {
				t.Error(err)
			}
			if test.sleep > 0 {
				time.Sleep(test.sleep)
			}
		}
	}

RESULT_LOOP:
	for _ = range tests {
		r := <-rc
		for i := range tests {
			test := &tests[i]
			if fmt.Sprint(test.meta) == fmt.Sprint(r.Meta) {
				test.fossilized = true
				if !reflect.DeepEqual(r.Data, test.data) {
					got := fmt.Sprintf("%x", r.Data)
					want := fmt.Sprintf("%x", test.data)
					t.Errorf("test#%d: Data = %q want %q", i, got, want)
				}
				evidence := r.Evidence.(*EvidenceWrapper).Evidence
				if !reflect.DeepEqual(evidence.Path, test.path) {
					got, _ := json.MarshalIndent(evidence.Path, "", "  ")
					want, _ := json.MarshalIndent(test.path, "", "  ")
					t.Errorf("test#%d: Path = %s\nwant %s", i, got, want)
				}
				continue RESULT_LOOP
			}
		}
		a := fmt.Sprintf("%x", r.Meta)
		t.Errorf("unexpected Meta %q", a)
	}

	for i, test := range tests {
		if !test.fossilized {
			t.Errorf("test#%d: not fossilized", i)
		}
	}
}

func benchmarkFossilize(b *testing.B, config *Config) {
	a, err := New(config)
	if err != nil {
		b.Fatal(err)
	}

	rc := make(chan *fossilizer.Result)
	a.AddResultChan(rc)

	go func() {
		if err := a.Start(); err != nil {
			b.Error(err)
		}
	}()

	defer func() {
		if err := a.Stop(); err != nil {
			b.Error(err)
		}
		close(rc)
	}()

	data := make([][]byte, b.N)
	for i := 0; i < b.N; i++ {
		data[i] = atos(*testutil.RandomHash())
	}

	b.ResetTimer()

	go func() {
		for i := 0; i < b.N; i++ {
			if err := a.Fossilize(data[i], data[i]); err != nil {
				b.Error(err)
			}
		}
	}()

	for i := 0; i < b.N; i++ {
		<-rc
	}
}

func atos(a types.Bytes32) []byte {
	return a[:]
}
<commit_msg>batchfossilizer: Disable output during benchmarks<commit_after>// Copyright 2016 Stratumn SAS. All rights reserved.
// Use of this source code is governed by the license
// that can be found in the LICENSE file.

package batchfossilizer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"reflect"
	"testing"
	"time"

	"github.com/stratumn/go/fossilizer"
	"github.com/stratumn/go/testutil"
	"github.com/stratumn/go/types"
	"github.com/stratumn/goprivate/merkle"
)

type fossilizeTest struct {
	data       []byte
	meta       []byte
	path       merkle.Path
	sleep      time.Duration
	fossilized bool
}

func testFossilizeMultiple(t *testing.T, a *Fossilizer, tests []fossilizeTest, start bool, fossilize bool) {
	rc := make(chan *fossilizer.Result)
	a.AddResultChan(rc)

	if start {
		go func() {
			if err := a.Start(); err != nil {
				t.Error(err)
			}
		}()
		defer func() {
			if err := a.Stop(); err != nil {
				t.Error(err)
			}
			close(rc)
		}()
	}

	if fossilize {
		for _, test := range tests {
			if err := a.Fossilize(test.data, test.meta); err != nil {
				t.Error(err)
			}
			if test.sleep > 0 {
				time.Sleep(test.sleep)
			}
		}
	}

RESULT_LOOP:
	for _ = range tests {
		r := <-rc
		for i := range tests {
			test := &tests[i]
			if fmt.Sprint(test.meta) == fmt.Sprint(r.Meta) {
				test.fossilized = true
				if !reflect.DeepEqual(r.Data, test.data) {
					got := fmt.Sprintf("%x", r.Data)
					want := fmt.Sprintf("%x", test.data)
					t.Errorf("test#%d: Data = %q want %q", i, got, want)
				}
				evidence := r.Evidence.(*EvidenceWrapper).Evidence
				if !reflect.DeepEqual(evidence.Path, test.path) {
					got, _ := json.MarshalIndent(evidence.Path, "", "  ")
					want, _ := json.MarshalIndent(test.path, "", "  ")
					t.Errorf("test#%d: Path = %s\nwant %s", i, got, want)
				}
				continue RESULT_LOOP
			}
		}
		a := fmt.Sprintf("%x", r.Meta)
		t.Errorf("unexpected Meta %q", a)
	}

	for i, test := range tests {
		if !test.fossilized {
			t.Errorf("test#%d: not fossilized", i)
		}
	}
}

func benchmarkFossilize(b *testing.B, config *Config) {
	a, err := New(config)
	if err != nil {
		b.Fatal(err)
	}

	rc := make(chan *fossilizer.Result)
	a.AddResultChan(rc)

	go func() {
		if err := a.Start(); err != nil {
			b.Error(err)
		}
	}()

	defer func() {
		if err := a.Stop(); err != nil {
			b.Error(err)
		}
		close(rc)
	}()

	data := make([][]byte, b.N)
	for i := 0; i < b.N; i++ {
		data[i] = atos(*testutil.RandomHash())
	}

	b.ResetTimer()
	log.SetOutput(ioutil.Discard)

	go func() {
		for i := 0; i < b.N; i++ {
			if err := a.Fossilize(data[i], data[i]); err != nil {
				b.Error(err)
			}
		}
	}()

	for i := 0; i < b.N; i++ {
		<-rc
	}
}

func atos(a types.Bytes32) []byte {
	return a[:]
}
<|endoftext|>


<commit_before>package azurerm

import (
	"os"
	"testing"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
	testAccProvider = Provider().(*schema.Provider)
	testAccProviders = map[string]terraform.ResourceProvider{
		"azurerm": testAccProvider,
	}
}

func TestProvider(t *testing.T) {
	if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
		t.Fatalf("err: %s", err)
	}
}

func TestProvider_impl(t *testing.T) {
	var _ terraform.ResourceProvider = Provider()
}

func testAccPreCheck(t *testing.T) {
	subscriptionID := os.Getenv("ARM_SUBSCRIPTION_ID")
	clientID := os.Getenv("ARM_CLIENT_ID")
	clientSecret := os.Getenv("ARM_CLIENT_SECRET")
	tenantID := os.Getenv("ARM_TENANT_ID")
	testLocation := os.Getenv("ARM_TEST_LOCATION")

	if subscriptionID == "" || clientID == "" || clientSecret == "" || tenantID == "" || testLocation == "" {
		t.Fatal("ARM_SUBSCRIPTION_ID, ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID and ARM_TEST_LOCATION must be set for acceptance tests")
	}
}

func testLocation() string {
	return os.Getenv("ARM_TEST_LOCATION")
}
<commit_msg>Refactoring + Environment Variable for an Alternate Location<commit_after>package azurerm

import (
	"os"
	"testing"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
	testAccProvider = Provider().(*schema.Provider)
	testAccProviders = map[string]terraform.ResourceProvider{
		"azurerm": testAccProvider,
	}
}

func TestProvider(t *testing.T) {
	if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
		t.Fatalf("err: %s", err)
	}
}

func TestProvider_impl(t *testing.T) {
	var _ terraform.ResourceProvider = Provider()
}

func testAccPreCheck(t *testing.T) {
	variables := []string{
		"ARM_SUBSCRIPTION_ID",
		"ARM_CLIENT_ID",
		"ARM_CLIENT_SECRET",
		"ARM_TENANT_ID",
		"ARM_TEST_LOCATION",
		"ARM_TEST_LOCATION_ALT",
	}

	for _, variable := range variables {
		value := os.Getenv(variable)
		if value == "" {
			t.Fatalf("`%s` must be set for acceptance tests!", variable)
		}
	}
}

func testLocation() string {
	return os.Getenv("ARM_TEST_LOCATION")
}

func testAltLocation() string {
	return os.Getenv("ARM_TEST_LOCATION_ALT")
}
<|endoftext|>


<commit_before>package pipe

import "github.com/qlova/ilang/src"
import "github.com/qlova/ilang/src/types/letter"

var Type = ilang.NewType("pipe", "RELAY", "TAKE")

func ScanExpression(ic *ilang.Compiler) string {
	var token = ic.LastToken
	//Types.
	if token == "|" {
		ic.Scan('|')
		var name = ic.Tmp("pipe")
		ic.Assembly("PIPE ", name)

		ic.ExpressionType = Type

		return name
	}
	return ""
}

func init() {
	ilang.RegisterStatement(Type, ScanPipeStatement)
	ilang.RegisterSymbol("|", ScanPipeSymbol)
	ilang.RegisterExpression(ScanExpression)

	ilang.RegisterFunction("open_m_text", ilang.Method(Type, true, "OPEN"))
	ilang.RegisterFunction("open_m_number", ilang.Function{Exists:true, Returns:[]ilang.Type{Type}, Data: `
FUNCTION open_m_number
	PULL value
	ARRAY tmp
	PUT value
	SHARE tmp
	OPEN
RETURN
	`})
	ilang.RegisterFunction("read_m_pipe", ilang.InlineFunction(nil, "PUSH 0\nIN", []ilang.Type{ilang.Text}))

	ilang.RegisterFunction("close", ilang.Function{Exists:true, Args:[]ilang.Type{Type}, Data: `
FUNCTION close
	TAKE file
	CLOSE file
RETURN
	`})

	ilang.RegisterShunt("(", func(ic *ilang.Compiler, name string) string {
		//Calling pipes.
		if ic.ExpressionType == Type {

			token := ic.Scan(0)
			if token == ")" {
				//Read default from the pipe.
				var r = ic.Tmp("read")
				ic.Assembly("RELAY ", name)
				ic.Assembly("PUSH 0")
				ic.Assembly("IN")
				ic.Assembly("GRAB ", r)
				ic.ExpressionType = ilang.Text
				return ic.Shunt(r)
			}

			ic.NextToken = token

			argument := ic.ScanExpression()

			switch ic.ExpressionType {
				case letter.Type:
					var r = ic.Tmp("reada")
					ic.Assembly("RELAY ", name)
					ic.Assembly("PUSH ", argument)
					ic.Assembly("RUN reada_m_pipe")
					ic.Assembly("GRAB ", r)
					ic.LoadFunction("reada_m_pipe")
					ic.ExpressionType = ilang.Text
					ic.Scan(')')
					return ic.Shunt(r)
				case ilang.Number:
					var r = ic.Tmp("read")
					ic.Assembly("RELAY ", name)
					ic.Assembly("PUSH ", argument)
					ic.Assembly("IN")
					ic.Assembly("GRAB ", r)
					ic.ExpressionType = ilang.Text
					ic.Scan(')')
					return ic.Shunt(r)
				default:
					ic.RaiseError("Cannot call a pipe with a ", ic.ExpressionType.Name, " argument in an expression!")
			}

		}
		return ""
	})

	ilang.RegisterShunt(".", func(ic *ilang.Compiler, name string) string {
		if ic.ExpressionType == Type {
			info := ic.Scan(0)

			ic.Assembly("RELAY ", name)
			ic.Assembly("SHARE ", ic.ParseString("\""+info+"\""))

			ic.Assembly("STAT")
			result := ic.Tmp(info)
			ic.Assembly("GRAB ", result)

			ic.ExpressionType = ilang.Text

			return result
		}
		return ""
	})
}

func ScanPipeSymbol(ic *ilang.Compiler) ilang.Type {
	ic.Scan('|')
	return Type
}

/*
	Scan a pipe statement, eg.
		file("text to write")
		file = newfile
*/
func ScanPipeStatement(ic *ilang.Compiler) {
	var name = ic.Scan(ilang.Name)
	var token = ic.Scan(0)
	switch token {
		case "(":
			argument := ic.ScanExpression()
			ic.Scan(')')
			if ic.ExpressionType != ilang.Text && ic.ExpressionType != ilang.Array {
				if ic.ExpressionType == ilang.Number {
					ic.Assembly("RELAY ", name)
					if argument != "" {
						ic.Assembly("PUSH ", argument)
					} else {
						ic.Assembly("PUSH 0")
					}
					ic.Assembly("IN")
					ic.Assembly("GRAB ", ic.Tmp("discard"))
					return
				}
				ic.RaiseError("Only text and number values can be passed to a pipe call (outside of an expression).")
			}
			ic.Assembly("RELAY ", name)
			ic.Assembly("SHARE ", argument)
			ic.Assembly("OUT")
		case "=":
			value := ic.ScanExpression()
			if ic.ExpressionType != Type {
				ic.RaiseError("Only ",Type.Name," values can be assigned to ",name,".")
			}
			ic.Assembly("RELAY ", value)
			ic.Assembly("RELOAD ", name)
		default:
			ic.ExpressionType = Type
			ic.NextToken = token
			ic.Shunt(name)
			if ic.ExpressionType != ilang.Undefined {
				ic.RaiseError("blank expression!")
			}
	}
}
<commit_msg>Pipes need to marked when renamed.<commit_after>package pipe

import "github.com/qlova/ilang/src"
import "github.com/qlova/ilang/src/types/letter"

var Type = ilang.NewType("pipe", "RELAY", "TAKE")

func ScanExpression(ic *ilang.Compiler) string {
	var token = ic.LastToken
	//Types.
	if token == "|" {
		ic.Scan('|')
		var name = ic.Tmp("pipe")
		ic.Assembly("PIPE ", name)

		ic.ExpressionType = Type

		return name
	}
	return ""
}

func init() {
	ilang.RegisterStatement(Type, ScanPipeStatement)
	ilang.RegisterSymbol("|", ScanPipeSymbol)
	ilang.RegisterExpression(ScanExpression)

	ilang.RegisterFunction("open_m_text", ilang.Method(Type, true, "OPEN"))
	ilang.RegisterFunction("open_m_number", ilang.Function{Exists:true, Returns:[]ilang.Type{Type}, Data: `
FUNCTION open_m_number
	PULL value
	ARRAY tmp
	PUT value
	SHARE tmp
	OPEN
RETURN
	`})
	ilang.RegisterFunction("read_m_pipe", ilang.InlineFunction(nil, "PUSH 0\nIN", []ilang.Type{ilang.Text}))

	ilang.RegisterFunction("close", ilang.Function{Exists:true, Args:[]ilang.Type{Type}, Data: `
FUNCTION close
	TAKE file
	CLOSE file
RETURN
	`})

	ilang.RegisterShunt("(", func(ic *ilang.Compiler, name string) string {
		//Calling pipes.
		if ic.ExpressionType == Type {

			token := ic.Scan(0)
			if token == ")" {
				//Read default from the pipe.
				var r = ic.Tmp("read")
				ic.Assembly("RELAY ", name)
				ic.Assembly("PUSH 0")
				ic.Assembly("IN")
				ic.Assembly("GRAB ", r)
				ic.ExpressionType = ilang.Text
				return ic.Shunt(r)
			}

			ic.NextToken = token

			argument := ic.ScanExpression()

			switch ic.ExpressionType {
				case letter.Type:
					var r = ic.Tmp("reada")
					ic.Assembly("RELAY ", name)
					ic.Assembly("PUSH ", argument)
					ic.Assembly("RUN reada_m_pipe")
					ic.Assembly("GRAB ", r)
					ic.LoadFunction("reada_m_pipe")
					ic.ExpressionType = ilang.Text
					ic.Scan(')')
					return ic.Shunt(r)
				case ilang.Number:
					var r = ic.Tmp("read")
					ic.Assembly("RELAY ", name)
					ic.Assembly("PUSH ", argument)
					ic.Assembly("IN")
					ic.Assembly("GRAB ", r)
					ic.ExpressionType = ilang.Text
					ic.Scan(')')
					return ic.Shunt(r)
				default:
					ic.RaiseError("Cannot call a pipe with a ", ic.ExpressionType.Name, " argument in an expression!")
			}

		}
		return ""
	})

	ilang.RegisterShunt(".", func(ic *ilang.Compiler, name string) string {
		if ic.ExpressionType == Type {
			info := ic.Scan(0)

			ic.Assembly("RELAY ", name)
			ic.Assembly("SHARE ", ic.ParseString("\""+info+"\""))

			ic.Assembly("STAT")
			result := ic.Tmp(info)
			ic.Assembly("GRAB ", result)

			ic.ExpressionType = ilang.Text

			return result
		}
		return ""
	})
}

func ScanPipeSymbol(ic *ilang.Compiler) ilang.Type {
	ic.Scan('|')
	return Type
}

/*
	Scan a pipe statement, eg.
		file("text to write")
		file = newfile
*/
func ScanPipeStatement(ic *ilang.Compiler) {
	var name = ic.Scan(ilang.Name)
	var token = ic.Scan(0)
	switch token {
		case "(":
			argument := ic.ScanExpression()
			ic.Scan(')')
			if ic.ExpressionType != ilang.Text && ic.ExpressionType != ilang.Array {
				if ic.ExpressionType == ilang.Number {
					ic.Assembly("RELAY ", name)
					if argument != "" {
						ic.Assembly("PUSH ", argument)
					} else {
						ic.Assembly("PUSH 0")
					}
					ic.Assembly("IN")
					ic.Assembly("GRAB ", ic.Tmp("discard"))
					return
				}
				ic.RaiseError("Only text and number values can be passed to a pipe call (outside of an expression).")
			}
			ic.Assembly("RELAY ", name)
			ic.Assembly("SHARE ", argument)
			ic.Assembly("OUT")
		case "=":
			value := ic.ScanExpression()
			if ic.ExpressionType != Type {
				ic.RaiseError("Only ",Type.Name," values can be assigned to ",name,".")
			}
			ic.Assembly("RELAY ", value)
			ic.Assembly("RELOAD ", name)

			ic.MarkVariable(name, "renamed")
		default:
			ic.ExpressionType = Type
			ic.NextToken = token
			ic.Shunt(name)
			if ic.ExpressionType != ilang.Undefined {
				ic.RaiseError("blank expression!")
			}
	}
}
<|endoftext|>


<commit_before><commit_msg>Modified tls_test_server to pass go vet.<commit_after><|endoftext|>


<commit_before>// +build linux

package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/opencontainers/runc/libcontainer/cgroups"
	"github.com/opencontainers/runc/libcontainer/configs"
	"github.com/opencontainers/runc/libcontainer/devices"
	"github.com/opencontainers/specs"
)

var specCommand = cli.Command{
	Name:  "spec",
	Usage: "create a new specification file",
	Action: func(context *cli.Context) {
		spec := specs.LinuxSpec{
			Spec: specs.Spec{
				Version: specs.Version,
				Platform: specs.Platform{
					OS:   runtime.GOOS,
					Arch: runtime.GOARCH,
				},
				Root: specs.Root{
					Path:     "rootfs",
					Readonly: true,
				},
				Process: specs.Process{
					Terminal: true,
					User:     specs.User{},
					Args: []string{
						"sh",
					},
					Env: []string{
						"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
						"TERM=xterm",
					},
				},
				Hostname: "shell",
				Mounts: []specs.Mount{
					{
						Type:        "proc",
						Source:      "proc",
						Destination: "/proc",
						Options:     "",
					},
					{
						Type:        "tmpfs",
						Source:      "tmpfs",
						Destination: "/dev",
						Options:     "nosuid,strictatime,mode=755,size=65536k",
					},
					{
						Type:        "devpts",
						Source:      "devpts",
						Destination: "/dev/pts",
						Options:     "nosuid,noexec,newinstance,ptmxmode=0666,mode=0620,gid=5",
					},
					{
						Type:        "tmpfs",
						Source:      "shm",
						Destination: "/dev/shm",
						Options:     "nosuid,noexec,nodev,mode=1777,size=65536k",
					},
					{
						Type:        "mqueue",
						Source:      "mqueue",
						Destination: "/dev/mqueue",
						Options:     "nosuid,noexec,nodev",
					},
					{
						Type:        "sysfs",
						Source:      "sysfs",
						Destination: "/sys",
						Options:     "nosuid,noexec,nodev",
					},
					{
						Type:        "cgroup",
						Source:      "cgroup",
						Destination: "/sys/fs/cgroup",
						Options:     "nosuid,noexec,nodev,relatime,ro",
					},
				},
			},
			Linux: specs.Linux{
				Namespaces: []specs.Namespace{
					{
						Type: "process",
					},
					{
						Type: "network",
					},
					{
						Type: "ipc",
					},
					{
						Type: "uts",
					},
					{
						Type: "mount",
					},
				},
				Capabilities: []string{
					"AUDIT_WRITE",
					"KILL",
					"NET_BIND_SERVICE",
				},
				Devices: []string{
					"null",
					"random",
					"full",
					"tty",
					"zero",
					"urandom",
				},
				Resources: specs.Resources{
					Memory: specs.Memory{
						Swappiness: -1,
					},
				},
			},
		}
		data, err := json.MarshalIndent(&spec, "", "\t")
		if err != nil {
			logrus.Fatal(err)
		}
		fmt.Printf("%s", data)
	},
}

var namespaceMapping = map[string]configs.NamespaceType{
	"process": configs.NEWPID,
	"network": configs.NEWNET,
	"mount":   configs.NEWNS,
	"user":    configs.NEWUSER,
	"ipc":     configs.NEWIPC,
	"uts":     configs.NEWUTS,
}

// loadSpec loads the specification from the provided path.
// If the path is empty then the default path will be "config.json"
func loadSpec(path string) (*specs.LinuxSpec, error) {
	if path == "" {
		path = "config.json"
	}
	f, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("JSON specification file for %s not found", path)
		}
		return nil, err
	}
	defer f.Close()
	var s *specs.LinuxSpec
	if err := json.NewDecoder(f).Decode(&s); err != nil {
		return nil, err
	}
	return s, checkSpecVersion(s)
}

// checkSpecVersion makes sure that the spec version matches runc's while we are in the initial
// development period.  It is better to hard fail than have missing fields or options in the spec.
func checkSpecVersion(s *specs.LinuxSpec) error {
	if s.Version != specs.Version {
		return fmt.Errorf("spec version is not compatible with implemented version %q: spec %q", specs.Version, s.Version)
	}
	return nil
}

func createLibcontainerConfig(spec *specs.LinuxSpec) (*configs.Config, error) {
	cwd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	rootfsPath := spec.Root.Path
	if !filepath.IsAbs(rootfsPath) {
		rootfsPath = filepath.Join(cwd, rootfsPath)
	}
	config := &configs.Config{
		Rootfs:       rootfsPath,
		Capabilities: spec.Linux.Capabilities,
		Readonlyfs:   spec.Root.Readonly,
		Hostname:     spec.Hostname,
		Privatefs:    true,
	}
	for _, ns := range spec.Linux.Namespaces {
		t, exists := namespaceMapping[ns.Type]
		if !exists {
			return nil, fmt.Errorf("namespace %q does not exist", ns)
		}
		config.Namespaces.Add(t, ns.Path)
	}
	if config.Namespaces.Contains(configs.NEWNET) {
		config.Networks = []*configs.Network{
			{
				Type: "loopback",
			},
		}
	}
	for _, m := range spec.Mounts {
		config.Mounts = append(config.Mounts, createLibcontainerMount(cwd, m))
	}
	if err := createDevices(spec, config); err != nil {
		return nil, err
	}
	if err := setupUserNamespace(spec, config); err != nil {
		return nil, err
	}
	c, err := createCgroupConfig(spec, config.Devices)
	if err != nil {
		return nil, err
	}
	config.Cgroups = c
	if config.Readonlyfs {
		setReadonly(config)
		config.MaskPaths = []string{
			"/proc/kcore",
		}
		config.ReadonlyPaths = []string{
			"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
		}
	}
	config.Sysctl = spec.Linux.Sysctl
	return config, nil
}

func createLibcontainerMount(cwd string, m specs.Mount) *configs.Mount {
	flags, data := parseMountOptions(m.Options)
	source := m.Source
	if m.Type == "bind" {
		if !filepath.IsAbs(source) {
			source = filepath.Join(cwd, m.Source)
		}
	}
	return &configs.Mount{
		Device:      m.Type,
		Source:      source,
		Destination: m.Destination,
		Data:        data,
		Flags:       flags,
	}
}

func createCgroupConfig(spec *specs.LinuxSpec, devices []*configs.Device) (*configs.Cgroup, error) {
	myCgroupPath, err := cgroups.GetThisCgroupDir("devices")
	if err != nil {
		return nil, err
	}
	c := &configs.Cgroup{
		Name:           getDefaultID(),
		Parent:         myCgroupPath,
		AllowedDevices: append(devices, allowedDevices...),
	}
	r := spec.Linux.Resources
	c.Memory = r.Memory.Limit
	c.MemoryReservation = r.Memory.Reservation
	c.MemorySwap = r.Memory.Swap
	c.KernelMemory = r.Memory.Kernel
	c.MemorySwappiness = r.Memory.Swappiness
	c.CpuShares = r.CPU.Shares
	c.CpuQuota = r.CPU.Quota
	c.CpuPeriod = r.CPU.Period
	c.CpuRtRuntime = r.CPU.RealtimeRuntime
	c.CpuRtPeriod = r.CPU.RealtimePeriod
	c.CpusetCpus = r.CPU.Cpus
	c.CpusetMems = r.CPU.Mems
	c.BlkioThrottleReadBpsDevice = r.BlockIO.ThrottleReadBpsDevice
	c.BlkioThrottleWriteBpsDevice = r.BlockIO.ThrottleWriteBpsDevice
	c.BlkioThrottleReadIOpsDevice = r.BlockIO.ThrottleReadIOpsDevice
	c.BlkioThrottleWriteIOpsDevice = r.BlockIO.ThrottleWriteIOpsDevice
	c.BlkioWeight = r.BlockIO.Weight
	c.BlkioWeightDevice = r.BlockIO.WeightDevice
	for _, l := range r.HugepageLimits {
		c.HugetlbLimit = append(c.HugetlbLimit, &configs.HugepageLimit{
			Pagesize: l.Pagesize,
			Limit:    l.Limit,
		})
	}
	c.OomKillDisable = r.DisableOOMKiller
	c.NetClsClassid = r.Network.ClassID
	for _, m := range r.Network.Priorities {
		c.NetPrioIfpriomap = append(c.NetPrioIfpriomap, &configs.IfPrioMap{
			Interface: m.Name,
			Priority:  m.Priority,
		})
	}
	return c, nil
}

func createDevices(spec *specs.LinuxSpec, config *configs.Config) error {
	for _, name := range spec.Linux.Devices {
		d, err := devices.DeviceFromPath(filepath.Join("/dev", name), "rwm")
		if err != nil {
			return err
		}
		config.Devices = append(config.Devices, d)
	}
	return nil
}

func setReadonly(config *configs.Config) {
	for _, m := range config.Mounts {
		if m.Device == "sysfs" {
			m.Flags |= syscall.MS_RDONLY
		}
	}
}

func setupUserNamespace(spec *specs.LinuxSpec, config *configs.Config) error {
	if len(spec.Linux.UIDMappings) == 0 {
		return nil
	}
	config.Namespaces.Add(configs.NEWUSER, "")
	create := func(m specs.IDMapping) configs.IDMap {
		return configs.IDMap{
			HostID:      int(m.HostID),
			ContainerID: int(m.ContainerID),
			Size:        int(m.Size),
		}
	}
	for _, m := range spec.Linux.UIDMappings {
		config.UidMappings = append(config.UidMappings, create(m))
	}
	for _, m := range spec.Linux.GIDMappings {
		config.GidMappings = append(config.GidMappings, create(m))
	}
	rootUid, err := config.HostUID()
	if err != nil {
		return err
	}
	rootGid, err := config.HostGID()
	if err != nil {
		return err
	}
	for _, node := range config.Devices {
		node.Uid = uint32(rootUid)
		node.Gid = uint32(rootGid)
	}
	return nil
}

// parseMountOptions parses the string and returns the flags and any mount data that
// it contains.
func parseMountOptions(options string) (int, string) {
	var (
		flag int
		data []string
	)
	flags := map[string]struct {
		clear bool
		flag  int
	}{
		"async":         {true, syscall.MS_SYNCHRONOUS},
		"atime":         {true, syscall.MS_NOATIME},
		"bind":          {false, syscall.MS_BIND},
		"defaults":      {false, 0},
		"dev":           {true, syscall.MS_NODEV},
		"diratime":      {true, syscall.MS_NODIRATIME},
		"dirsync":       {false, syscall.MS_DIRSYNC},
		"exec":          {true, syscall.MS_NOEXEC},
		"mand":          {false, syscall.MS_MANDLOCK},
		"noatime":       {false, syscall.MS_NOATIME},
		"nodev":         {false, syscall.MS_NODEV},
		"nodiratime":    {false, syscall.MS_NODIRATIME},
		"noexec":        {false, syscall.MS_NOEXEC},
		"nomand":        {true, syscall.MS_MANDLOCK},
		"norelatime":    {true, syscall.MS_RELATIME},
		"nostrictatime": {true, syscall.MS_STRICTATIME},
		"nosuid":        {false, syscall.MS_NOSUID},
		"private":       {false, syscall.MS_PRIVATE},
		"rbind":         {false, syscall.MS_BIND | syscall.MS_REC},
		"relatime":      {false, syscall.MS_RELATIME},
		"remount":       {false, syscall.MS_REMOUNT},
		"ro":            {false, syscall.MS_RDONLY},
		"rprivate":      {false, syscall.MS_PRIVATE | syscall.MS_REC},
		"rshared":       {false, syscall.MS_SHARED | syscall.MS_REC},
		"rslave":        {false, syscall.MS_SLAVE | syscall.MS_REC},
		"runbindable":   {false, syscall.MS_UNBINDABLE | syscall.MS_REC},
		"rw":            {true, syscall.MS_RDONLY},
		"shared":        {false, syscall.MS_SHARED},
		"slave":         {false, syscall.MS_SLAVE},
		"strictatime":   {false, syscall.MS_STRICTATIME},
		"suid":          {true, syscall.MS_NOSUID},
		"sync":          {false, syscall.MS_SYNCHRONOUS},
		"unbindable":    {false, syscall.MS_UNBINDABLE},
	}
	for _, o := range strings.Split(options, ",") {
		// If the option does not exist in the flags table or the flag
		// is not supported on the platform,
		// then it is a data value for a specific fs type
		if f, exists := flags[o]; exists && f.flag != 0 {
			if f.clear {
				flag &= ^f.flag
			} else {
				flag |= f.flag
			}
		} else {
			data = append(data, o)
		}
	}
	return flag, strings.Join(data, ",")
}
<commit_msg>Rename process namespace to pid<commit_after>// +build linux

package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/opencontainers/runc/libcontainer/cgroups"
	"github.com/opencontainers/runc/libcontainer/configs"
	"github.com/opencontainers/runc/libcontainer/devices"
	"github.com/opencontainers/specs"
)

var specCommand = cli.Command{
	Name:  "spec",
	Usage: "create a new specification file",
	Action: func(context *cli.Context) {
		spec := specs.LinuxSpec{
			Spec: specs.Spec{
				Version: specs.Version,
				Platform: specs.Platform{
					OS:   runtime.GOOS,
					Arch: runtime.GOARCH,
				},
				Root: specs.Root{
					Path:     "rootfs",
					Readonly: true,
				},
				Process: specs.Process{
					Terminal: true,
					User:     specs.User{},
					Args: []string{
						"sh",
					},
					Env: []string{
						"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
						"TERM=xterm",
					},
				},
				Hostname: "shell",
				Mounts: []specs.Mount{
					{
						Type:        "proc",
						Source:      "proc",
						Destination: "/proc",
						Options:     "",
					},
					{
						Type:        "tmpfs",
						Source:      "tmpfs",
						Destination: "/dev",
						Options:     "nosuid,strictatime,mode=755,size=65536k",
					},
					{
						Type:        "devpts",
						Source:      "devpts",
						Destination: "/dev/pts",
						Options:     "nosuid,noexec,newinstance,ptmxmode=0666,mode=0620,gid=5",
					},
					{
						Type:        "tmpfs",
						Source:      "shm",
						Destination: "/dev/shm",
						Options:     "nosuid,noexec,nodev,mode=1777,size=65536k",
					},
					{
						Type:        "mqueue",
						Source:      "mqueue",
						Destination: "/dev/mqueue",
						Options:     "nosuid,noexec,nodev",
					},
					{
						Type:        "sysfs",
						Source:      "sysfs",
						Destination: "/sys",
						Options:     "nosuid,noexec,nodev",
					},
					{
						Type:        "cgroup",
						Source:      "cgroup",
						Destination: "/sys/fs/cgroup",
						Options:     "nosuid,noexec,nodev,relatime,ro",
					},
				},
			},
			Linux: specs.Linux{
				Namespaces: []specs.Namespace{
					{
						Type: "pid",
					},
					{
						Type: "network",
					},
					{
						Type: "ipc",
					},
					{
						Type: "uts",
					},
					{
						Type: "mount",
					},
				},
				Capabilities: []string{
					"AUDIT_WRITE",
					"KILL",
					"NET_BIND_SERVICE",
				},
				Devices: []string{
					"null",
					"random",
					"full",
					"tty",
					"zero",
					"urandom",
				},
				Resources: specs.Resources{
					Memory: specs.Memory{
						Swappiness: -1,
					},
				},
			},
		}
		data, err := json.MarshalIndent(&spec, "", "\t")
		if err != nil {
			logrus.Fatal(err)
		}
		fmt.Printf("%s", data)
	},
}

var namespaceMapping = map[string]configs.NamespaceType{
	"pid":     configs.NEWPID,
	"network": configs.NEWNET,
	"mount":   configs.NEWNS,
	"user":    configs.NEWUSER,
	"ipc":     configs.NEWIPC,
	"uts":     configs.NEWUTS,
}

// loadSpec loads the specification from the provided path.
// If the path is empty then the default path will be "config.json"
func loadSpec(path string) (*specs.LinuxSpec, error) {
	if path == "" {
		path = "config.json"
	}
	f, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("JSON specification file for %s not found", path)
		}
		return nil, err
	}
	defer f.Close()
	var s *specs.LinuxSpec
	if err := json.NewDecoder(f).Decode(&s); err != nil {
		return nil, err
	}
	return s, checkSpecVersion(s)
}

// checkSpecVersion makes sure that the spec version matches runc's while we are in the initial
// development period.  It is better to hard fail than have missing fields or options in the spec.
func checkSpecVersion(s *specs.LinuxSpec) error {
	if s.Version != specs.Version {
		return fmt.Errorf("spec version is not compatible with implemented version %q: spec %q", specs.Version, s.Version)
	}
	return nil
}

func createLibcontainerConfig(spec *specs.LinuxSpec) (*configs.Config, error) {
	cwd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	rootfsPath := spec.Root.Path
	if !filepath.IsAbs(rootfsPath) {
		rootfsPath = filepath.Join(cwd, rootfsPath)
	}
	config := &configs.Config{
		Rootfs:       rootfsPath,
		Capabilities: spec.Linux.Capabilities,
		Readonlyfs:   spec.Root.Readonly,
		Hostname:     spec.Hostname,
		Privatefs:    true,
	}
	for _, ns := range spec.Linux.Namespaces {
		t, exists := namespaceMapping[ns.Type]
		if !exists {
			return nil, fmt.Errorf("namespace %q does not exist", ns)
		}
		config.Namespaces.Add(t, ns.Path)
	}
	if config.Namespaces.Contains(configs.NEWNET) {
		config.Networks = []*configs.Network{
			{
				Type: "loopback",
			},
		}
	}
	for _, m := range spec.Mounts {
		config.Mounts = append(config.Mounts, createLibcontainerMount(cwd, m))
	}
	if err := createDevices(spec, config); err != nil {
		return nil, err
	}
	if err := setupUserNamespace(spec, config); err != nil {
		return nil, err
	}
	c, err := createCgroupConfig(spec, config.Devices)
	if err != nil {
		return nil, err
	}
	config.Cgroups = c
	if config.Readonlyfs {
		setReadonly(config)
		config.MaskPaths = []string{
			"/proc/kcore",
		}
		config.ReadonlyPaths = []string{
			"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
		}
	}
	config.Sysctl = spec.Linux.Sysctl
	return config, nil
}

func createLibcontainerMount(cwd string, m specs.Mount) *configs.Mount {
	flags, data := parseMountOptions(m.Options)
	source := m.Source
	if m.Type == "bind" {
		if !filepath.IsAbs(source) {
			source = filepath.Join(cwd, m.Source)
		}
	}
	return &configs.Mount{
		Device:      m.Type,
		Source:      source,
		Destination: m.Destination,
		Data:        data,
		Flags:       flags,
	}
}

func createCgroupConfig(spec *specs.LinuxSpec, devices []*configs.Device) (*configs.Cgroup, error) {
	myCgroupPath, err := cgroups.GetThisCgroupDir("devices")
	if err != nil {
		return nil, err
	}
	c := &configs.Cgroup{
		Name:           getDefaultID(),
		Parent:         myCgroupPath,
		AllowedDevices: append(devices, allowedDevices...),
	}
	r := spec.Linux.Resources
	c.Memory = r.Memory.Limit
	c.MemoryReservation = r.Memory.Reservation
	c.MemorySwap = r.Memory.Swap
	c.KernelMemory = r.Memory.Kernel
	c.MemorySwappiness = r.Memory.Swappiness
	c.CpuShares = r.CPU.Shares
	c.CpuQuota = r.CPU.Quota
	c.CpuPeriod = r.CPU.Period
	c.CpuRtRuntime = r.CPU.RealtimeRuntime
	c.CpuRtPeriod = r.CPU.RealtimePeriod
	c.CpusetCpus = r.CPU.Cpus
	c.CpusetMems = r.CPU.Mems
	c.BlkioThrottleReadBpsDevice = r.BlockIO.ThrottleReadBpsDevice
	c.BlkioThrottleWriteBpsDevice = r.BlockIO.ThrottleWriteBpsDevice
	c.BlkioThrottleReadIOpsDevice = r.BlockIO.ThrottleReadIOpsDevice
	c.BlkioThrottleWriteIOpsDevice = r.BlockIO.ThrottleWriteIOpsDevice
	c.BlkioWeight = r.BlockIO.Weight
	c.BlkioWeightDevice = r.BlockIO.WeightDevice
	for _, l := range r.HugepageLimits {
		c.HugetlbLimit = append(c.HugetlbLimit, &configs.HugepageLimit{
			Pagesize: l.Pagesize,
			Limit:    l.Limit,
		})
	}
	c.OomKillDisable = r.DisableOOMKiller
	c.NetClsClassid = r.Network.ClassID
	for _, m := range r.Network.Priorities {
		c.NetPrioIfpriomap = append(c.NetPrioIfpriomap, &configs.IfPrioMap{
			Interface: m.Name,
			Priority:  m.Priority,
		})
	}
	return c, nil
}

func createDevices(spec *specs.LinuxSpec, config *configs.Config) error {
	for _, name := range spec.Linux.Devices {
		d, err := devices.DeviceFromPath(filepath.Join("/dev", name), "rwm")
		if err != nil {
			return err
		}
		config.Devices = append(config.Devices, d)
	}
	return nil
}

func setReadonly(config *configs.Config) {
	for _, m := range config.Mounts {
		if m.Device == "sysfs" {
			m.Flags |= syscall.MS_RDONLY
		}
	}
}

func setupUserNamespace(spec *specs.LinuxSpec, config *configs.Config) error {
	if len(spec.Linux.UIDMappings) == 0 {
		return nil
	}
	config.Namespaces.Add(configs.NEWUSER, "")
	create := func(m specs.IDMapping) configs.IDMap {
		return configs.IDMap{
			HostID:      int(m.HostID),
			ContainerID: int(m.ContainerID),
			Size:        int(m.Size),
		}
	}
	for _, m := range spec.Linux.UIDMappings {
		config.UidMappings = append(config.UidMappings, create(m))
	}
	for _, m := range spec.Linux.GIDMappings {
		config.GidMappings = append(config.GidMappings, create(m))
	}
	rootUid, err := config.HostUID()
	if err != nil {
		return err
	}
	rootGid, err := config.HostGID()
	if err != nil {
		return err
	}
	for _, node := range config.Devices {
		node.Uid = uint32(rootUid)
		node.Gid = uint32(rootGid)
	}
	return nil
}

// parseMountOptions parses the string and returns the flags and any mount data that
// it contains.
func parseMountOptions(options string) (int, string) {
	var (
		flag int
		data []string
	)
	flags := map[string]struct {
		clear bool
		flag  int
	}{
		"async":         {true, syscall.MS_SYNCHRONOUS},
		"atime":         {true, syscall.MS_NOATIME},
		"bind":          {false, syscall.MS_BIND},
		"defaults":      {false, 0},
		"dev":           {true, syscall.MS_NODEV},
		"diratime":      {true, syscall.MS_NODIRATIME},
		"dirsync":       {false, syscall.MS_DIRSYNC},
		"exec":          {true, syscall.MS_NOEXEC},
		"mand":          {false, syscall.MS_MANDLOCK},
		"noatime":       {false, syscall.MS_NOATIME},
		"nodev":         {false, syscall.MS_NODEV},
		"nodiratime":    {false, syscall.MS_NODIRATIME},
		"noexec":        {false, syscall.MS_NOEXEC},
		"nomand":        {true, syscall.MS_MANDLOCK},
		"norelatime":    {true, syscall.MS_RELATIME},
		"nostrictatime": {true, syscall.MS_STRICTATIME},
		"nosuid":        {false, syscall.MS_NOSUID},
		"private":       {false, syscall.MS_PRIVATE},
		"rbind":         {false, syscall.MS_BIND | syscall.MS_REC},
		"relatime":      {false, syscall.MS_RELATIME},
		"remount":       {false, syscall.MS_REMOUNT},
		"ro":            {false, syscall.MS_RDONLY},
		"rprivate":      {false, syscall.MS_PRIVATE | syscall.MS_REC},
		"rshared":       {false, syscall.MS_SHARED | syscall.MS_REC},
		"rslave":        {false, syscall.MS_SLAVE | syscall.MS_REC},
		"runbindable":   {false, syscall.MS_UNBINDABLE | syscall.MS_REC},
		"rw":            {true, syscall.MS_RDONLY},
		"shared":        {false, syscall.MS_SHARED},
		"slave":         {false, syscall.MS_SLAVE},
		"strictatime":   {false, syscall.MS_STRICTATIME},
		"suid":          {true, syscall.MS_NOSUID},
		"sync":          {false, syscall.MS_SYNCHRONOUS},
		"unbindable":    {false, syscall.MS_UNBINDABLE},
	}
	for _, o := range strings.Split(options, ",") {
		// If the option does not exist in the flags table or the flag
		// is not supported on the platform,
		// then it is a data value for a specific fs type
		if f, exists := flags[o]; exists && f.flag != 0 {
			if f.clear {
				flag &= ^f.flag
			} else {
				flag |= f.flag
			}
		} else {
			data = append(data, o)
		}
	}
	return flag, strings.Join(data, ",")
}
<|endoftext|>


<commit_before>package udt

import (
	"errors"
	"fmt"
	"net"
	"syscall"
	"time"
	"unsafe"
)

// #cgo linux CFLAGS: -DLINUX
// #cgo darwin CFLAGS: -DOSX
// #cgo freebsd CFLAGS: -DBSD
// #cgo windows CFLAGS: -DERROR_NO_WINDOWS_SUPPORT
// #cgo i386 CFLAGS: -DIA32
// #cgo amd64 CFLAGS: -DAMD64
// #cgo CFLAGS: -Wall -finline-functions -O3 -fno-strict-aliasing -fvisibility=hidden
// #cgo LDFLAGS: -lstdc++ -lm
// #include "udt_c.h"
// #include <errno.h>
// #include <arpa/inet.h>
// #include <string.h>
import "C"

// returned when calling functions on a fd that's closing.
var errClosing = errors.New("file descriptor closing")

var (
	// UDP_RCVBUF_SIZE is the default UDP_RCVBUF size.
	UDP_RCVBUF_SIZE = uint32(20971520) // 20MB

	// UDT_SNDTIMEO is the udt_send() timeout in milliseconds
	// note this doesnt change the interface, we use it as a poor polling
	UDT_SNDTIMEO_MS = C.int(UDT_ASYNC_TIMEOUT)

	// UDT_RCVTIMEO is the udt_recv() timeout in milliseconds
	// note this doesnt change the interface, we use it as a poor polling
	UDT_RCVTIMEO_MS = C.int(UDT_ASYNC_TIMEOUT)

	// UDT_ASYNC_TIMEOUT (in ms)
	UDT_ASYNC_TIMEOUT = 40
)

// rebind this here for type safety
var INVALID_SOCK C.UDTSOCKET = C.UDTSOCKET(C.INVALID_SOCK)

func init() {
	// adjust the rcvbuf to our max.
	max, err := maxRcvBufSize()
	if err == nil {
		max = uint32(float32(max) * 0.5) // 0.5 of max.
		if max < UDP_RCVBUF_SIZE {
			UDP_RCVBUF_SIZE = max
		}
	}
}

type signal struct{}
type semaphore chan struct{}

// udtFD (wraps udt.socket)
type udtFD struct {
	refcnt int32
	bound  bool

	// immutable until Close
	sock C.UDTSOCKET

	net   string
	laddr *UDTAddr
	raddr *UDTAddr
}

func newFD(sock C.UDTSOCKET, laddr, raddr *UDTAddr, net string) (*udtFD, error) {
	lac := laddr.copy()
	rac := raddr.copy()
	fd := &udtFD{sock: sock, laddr: lac, raddr: rac, net: net}

	return fd, nil
}

// lastErrorOp returns the last error as a net.OpError.
func (fd *udtFD) lastErrorOp(op string) *net.OpError {
	return &net.OpError{
		Op:   op,
		Net:  fd.net,
		Addr: fd.laddr,
		Err:  lastError(),
	}
}

func (fd *udtFD) name() string {
	var ls, rs string
	if fd.laddr != nil {
		ls = fd.laddr.String()
	}
	if fd.raddr != nil {
		rs = fd.raddr.String()
	}
	return fd.net + ":" + ls + "->" + rs
}

func (fd *udtFD) bind() error {
	_, sa, salen, err := fd.laddr.socketArgs()
	if err != nil {
		return err
	}

	// cast sockaddr
	csa := (*C.struct_sockaddr)(unsafe.Pointer(sa))
	if C.udt_bind(fd.sock, csa, C.int(salen)) != 0 {
		return fd.lastErrorOp("bind")
	}

	return nil
}

func (fd *udtFD) listen(backlog int) error {

	if C.udt_listen(fd.sock, C.int(backlog)) == C.ERROR {
		return fd.lastErrorOp("listen")
	}
	return nil
}

func (fd *udtFD) accept() (*udtFD, error) {
	var sa syscall.RawSockaddrAny
	var salen C.int

	sock2 := C.udt_accept(fd.sock, (*C.struct_sockaddr)(unsafe.Pointer(&sa)), &salen)
	if sock2 == INVALID_SOCK {
		err := fd.lastErrorOp("accept")
		return nil, err
	}

	raddr, err := addrWithSockaddr(&sa)
	if err != nil {
		closeSocket(sock2)
		return nil, fmt.Errorf("error converting address: %s", err)
	}

	remotefd, err := newFD(sock2, fd.laddr, raddr, fd.net)
	if err != nil {
		closeSocket(sock2)
		return nil, err
	}

	return remotefd, nil
}

func (fd *udtFD) connect(raddr *UDTAddr) error {

	_, sa, salen, err := raddr.socketArgs()
	if err != nil {
		return err
	}
	csa := (*C.struct_sockaddr)(unsafe.Pointer(sa))

	if C.udt_connect(fd.sock, csa, C.int(salen)) == C.ERROR {
		err := lastError()
		return fmt.Errorf("error connecting: %s", err)
	}

	fd.raddr = raddr
	if fd.laddr == nil {
		var lsa syscall.RawSockaddrAny
		var namelen C.int
		if C.udt_getsockname(fd.sock, (*C.struct_sockaddr)(unsafe.Pointer(&lsa)), &namelen) == C.ERROR {
			err := lastError()
			return fmt.Errorf("error getting local sockaddr: %s", err)
		}
		laddr, err := addrWithSockaddr(&lsa)
		if err != nil {
			return err
		}

		fd.laddr = laddr
	}
	return nil
}

func (fd *udtFD) Close() error {
	err := closeSocket(fd.sock)
	fd.sock = -1
	if err != nil {
		if err.Error() == "Operation not supported: Invalid socket ID." {
			// this ones okay, just means its already closed, somewhere
			return nil
		}
		return err
	}
	return nil
}

// net.Conn functions

func (fd *udtFD) LocalAddr() net.Addr {
	return fd.laddr
}

func (fd *udtFD) RemoteAddr() net.Addr {
	return fd.raddr
}

func (fd *udtFD) SetDeadline(t time.Time) error {
	panic("not yet implemented")
}

func (fd *udtFD) SetReadDeadline(t time.Time) error {
	panic("not yet implemented")
}

func (fd *udtFD) SetWriteDeadline(t time.Time) error {
	panic("not yet implemented")
}

// lastError returns the last error as a Go string.
func lastError() error {
	return errors.New(C.GoString(C.udt_getlasterror_desc()))
}

func socket(addrfamily int) (sock C.UDTSOCKET, reterr error) {

	sock = C.udt_socket(C.int(addrfamily), C.SOCK_STREAM, 0)
	if sock == INVALID_SOCK {
		return INVALID_SOCK, fmt.Errorf("invalid socket: %s", lastError())
	}

	return sock, nil
}

func closeSocket(sock C.UDTSOCKET) error {
	if C.udt_close(sock) == C.ERROR {
		return lastError()
	}
	return nil
}

// dialFD sets up a udtFD
func dialFD(laddr, raddr *UDTAddr) (*udtFD, error) {

	if raddr == nil {
		return nil, &net.OpError{Op: "dial", Net: "udt", Addr: raddr, Err: errors.New("invalid remote address")}
	}

	if laddr != nil && laddr.AF() != raddr.AF() {
		return nil, &net.OpError{Op: "dial", Net: "udt", Addr: raddr, Err: errors.New("differing remote address network")}
	}

	sock, err := socket(raddr.AF())
	if err != nil {
		return nil, err
	}

	fd, err := newFD(sock, laddr, raddr, "udt")
	if err != nil {
		closeSocket(sock)
		return nil, err
	}

	if laddr != nil {
		if err := fd.bind(); err != nil {
			fd.Close()
			return nil, err
		}
	}

	if err := fd.connect(raddr); err != nil {
		fd.Close()
		return nil, err
	}

	return fd, nil
}

// listenFD sets up a udtFD
func listenFD(laddr *UDTAddr) (*udtFD, error) {

	if laddr == nil {
		return nil, &net.OpError{Op: "dial", Net: "udt", Err: errors.New("invalid address")}
	}

	sock, err := socket(laddr.AF())
	if err != nil {
		return nil, err
	}

	fd, err := newFD(sock, laddr, nil, "udt")
	if err != nil {
		closeSocket(sock)
		return nil, err
	}

	if err := fd.bind(); err != nil {
		fd.Close()
		return nil, err
	}

	// TODO: use maxListenerBacklog like golang.org/net/
	if err := fd.listen(syscall.SOMAXCONN); err != nil {
		fd.Close()
		return nil, err
	}

	return fd, nil
}
<commit_msg>implement read and write deadlines in fd<commit_after>package udt

import (
	"errors"
	"fmt"
	"net"
	"syscall"
	"time"
	"unsafe"
)

// #cgo linux CFLAGS: -DLINUX
// #cgo darwin CFLAGS: -DOSX
// #cgo freebsd CFLAGS: -DBSD
// #cgo windows CFLAGS: -DERROR_NO_WINDOWS_SUPPORT
// #cgo i386 CFLAGS: -DIA32
// #cgo amd64 CFLAGS: -DAMD64
// #cgo CFLAGS: -Wall -finline-functions -O3 -fno-strict-aliasing -fvisibility=hidden
// #cgo LDFLAGS: -lstdc++ -lm
// #include "udt_c.h"
// #include <errno.h>
// #include <arpa/inet.h>
// #include <string.h>
import "C"

// returned when calling functions on a fd that's closing.
var errClosing = errors.New("file descriptor closing")

var (
	// UDP_RCVBUF_SIZE is the default UDP_RCVBUF size.
	UDP_RCVBUF_SIZE = uint32(20971520) // 20MB

	// UDT_SNDTIMEO is the udt_send() timeout in milliseconds
	// note this doesnt change the interface, we use it as a poor polling
	UDT_SNDTIMEO_MS = C.int(UDT_ASYNC_TIMEOUT)

	// UDT_RCVTIMEO is the udt_recv() timeout in milliseconds
	// note this doesnt change the interface, we use it as a poor polling
	UDT_RCVTIMEO_MS = C.int(UDT_ASYNC_TIMEOUT)

	// UDT_ASYNC_TIMEOUT (in ms)
	UDT_ASYNC_TIMEOUT = 40
)

// rebind this here for type safety
var INVALID_SOCK C.UDTSOCKET = C.UDTSOCKET(C.INVALID_SOCK)

func init() {
	// adjust the rcvbuf to our max.
	max, err := maxRcvBufSize()
	if err == nil {
		max = uint32(float32(max) * 0.5) // 0.5 of max.
		if max < UDP_RCVBUF_SIZE {
			UDP_RCVBUF_SIZE = max
		}
	}
}

type signal struct{}
type semaphore chan struct{}

// udtFD (wraps udt.socket)
type udtFD struct {
	refcnt int32
	bound  bool

	// immutable until Close
	sock C.UDTSOCKET

	net   string
	laddr *UDTAddr
	raddr *UDTAddr
}

func newFD(sock C.UDTSOCKET, laddr, raddr *UDTAddr, net string) (*udtFD, error) {
	lac := laddr.copy()
	rac := raddr.copy()
	fd := &udtFD{sock: sock, laddr: lac, raddr: rac, net: net}

	return fd, nil
}

// lastErrorOp returns the last error as a net.OpError.
func (fd *udtFD) lastErrorOp(op string) *net.OpError {
	return &net.OpError{
		Op:   op,
		Net:  fd.net,
		Addr: fd.laddr,
		Err:  lastError(),
	}
}

func (fd *udtFD) name() string {
	var ls, rs string
	if fd.laddr != nil {
		ls = fd.laddr.String()
	}
	if fd.raddr != nil {
		rs = fd.raddr.String()
	}
	return fd.net + ":" + ls + "->" + rs
}

func (fd *udtFD) bind() error {
	_, sa, salen, err := fd.laddr.socketArgs()
	if err != nil {
		return err
	}

	// cast sockaddr
	csa := (*C.struct_sockaddr)(unsafe.Pointer(sa))
	if C.udt_bind(fd.sock, csa, C.int(salen)) != 0 {
		return fd.lastErrorOp("bind")
	}

	return nil
}

func (fd *udtFD) listen(backlog int) error {

	if C.udt_listen(fd.sock, C.int(backlog)) == C.ERROR {
		return fd.lastErrorOp("listen")
	}
	return nil
}

func (fd *udtFD) accept() (*udtFD, error) {
	var sa syscall.RawSockaddrAny
	var salen C.int

	sock2 := C.udt_accept(fd.sock, (*C.struct_sockaddr)(unsafe.Pointer(&sa)), &salen)
	if sock2 == INVALID_SOCK {
		err := fd.lastErrorOp("accept")
		return nil, err
	}

	raddr, err := addrWithSockaddr(&sa)
	if err != nil {
		closeSocket(sock2)
		return nil, fmt.Errorf("error converting address: %s", err)
	}

	remotefd, err := newFD(sock2, fd.laddr, raddr, fd.net)
	if err != nil {
		closeSocket(sock2)
		return nil, err
	}

	return remotefd, nil
}

func (fd *udtFD) connect(raddr *UDTAddr) error {

	_, sa, salen, err := raddr.socketArgs()
	if err != nil {
		return err
	}
	csa := (*C.struct_sockaddr)(unsafe.Pointer(sa))

	if C.udt_connect(fd.sock, csa, C.int(salen)) == C.ERROR {
		err := lastError()
		return fmt.Errorf("error connecting: %s", err)
	}

	fd.raddr = raddr
	if fd.laddr == nil {
		var lsa syscall.RawSockaddrAny
		var namelen C.int
		if C.udt_getsockname(fd.sock, (*C.struct_sockaddr)(unsafe.Pointer(&lsa)), &namelen) == C.ERROR {
			err := lastError()
			return fmt.Errorf("error getting local sockaddr: %s", err)
		}
		laddr, err := addrWithSockaddr(&lsa)
		if err != nil {
			return err
		}

		fd.laddr = laddr
	}
	return nil
}

func (fd *udtFD) Close() error {
	err := closeSocket(fd.sock)
	fd.sock = -1
	if err != nil {
		if err.Error() == "Operation not supported: Invalid socket ID." {
			// this ones okay, just means its already closed, somewhere
			return nil
		}
		return err
	}
	return nil
}

// net.Conn functions

func (fd *udtFD) LocalAddr() net.Addr {
	return fd.laddr
}

func (fd *udtFD) RemoteAddr() net.Addr {
	return fd.raddr
}

func (fd *udtFD) SetDeadline(t time.Time) error {
	err := fd.SetReadDeadline(t)
	if err != nil {
		return err
	}
	return fd.SetWriteDeadline(t)
}

func (fd *udtFD) SetReadDeadline(t time.Time) error {
	d := C.int(t.Sub(time.Now()).Nanoseconds() / 1e6)
	if C.udt_setsockopt(fd.sock, 0, C.UDT_RCVTIMEO, unsafe.Pointer(&d), C.sizeof_int) != 0 {
		return fmt.Errorf("failed to set ReadDeadline: %s", lastError())
	}
	return nil
}

func (fd *udtFD) SetWriteDeadline(t time.Time) error {
	d := C.int(t.Sub(time.Now()).Nanoseconds() / 1e6)
	if C.udt_setsockopt(fd.sock, 0, C.UDT_SNDTIMEO, unsafe.Pointer(&d), C.sizeof_int) != 0 {
		return fmt.Errorf("failed to set WriteDeadline: %s", lastError())
	}
	return nil
}

// lastError returns the last error as a Go string.
func lastError() error {
	return errors.New(C.GoString(C.udt_getlasterror_desc()))
}

func socket(addrfamily int) (sock C.UDTSOCKET, reterr error) {

	sock = C.udt_socket(C.int(addrfamily), C.SOCK_STREAM, 0)
	if sock == INVALID_SOCK {
		return INVALID_SOCK, fmt.Errorf("invalid socket: %s", lastError())
	}

	return sock, nil
}

func closeSocket(sock C.UDTSOCKET) error {
	if C.udt_close(sock) == C.ERROR {
		return lastError()
	}
	return nil
}

// dialFD sets up a udtFD
func dialFD(laddr, raddr *UDTAddr) (*udtFD, error) {

	if raddr == nil {
		return nil, &net.OpError{Op: "dial", Net: "udt", Addr: raddr, Err: errors.New("invalid remote address")}
	}

	if laddr != nil && laddr.AF() != raddr.AF() {
		return nil, &net.OpError{Op: "dial", Net: "udt", Addr: raddr, Err: errors.New("differing remote address network")}
	}

	sock, err := socket(raddr.AF())
	if err != nil {
		return nil, err
	}

	fd, err := newFD(sock, laddr, raddr, "udt")
	if err != nil {
		closeSocket(sock)
		return nil, err
	}

	if laddr != nil {
		if err := fd.bind(); err != nil {
			fd.Close()
			return nil, err
		}
	}

	if err := fd.connect(raddr); err != nil {
		fd.Close()
		return nil, err
	}

	return fd, nil
}

// listenFD sets up a udtFD
func listenFD(laddr *UDTAddr) (*udtFD, error) {

	if laddr == nil {
		return nil, &net.OpError{Op: "dial", Net: "udt", Err: errors.New("invalid address")}
	}

	sock, err := socket(laddr.AF())
	if err != nil {
		return nil, err
	}

	fd, err := newFD(sock, laddr, nil, "udt")
	if err != nil {
		closeSocket(sock)
		return nil, err
	}

	if err := fd.bind(); err != nil {
		fd.Close()
		return nil, err
	}

	// TODO: use maxListenerBacklog like golang.org/net/
	if err := fd.listen(syscall.SOMAXCONN); err != nil {
		fd.Close()
		return nil, err
	}

	return fd, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var path string // path to search
var args []string

// isDir accepts a string (file path) and returns
// a boolean which indicates if the path is
// a valid directory.
func isDir(path string) bool {
	stat, err := os.Stat(path)
	if err != nil {
		log.Fatal(err)
	}
	return stat.IsDir()
}

func init() {
	// Set up command-line flags.
	flag.StringVar(&path, "p", ".", "path")
	flag.Parse()
	// Validate flags.
	if !isDir(path) {
		log.Fatal(path, "is not a valid path.")
	}
	args = flag.Args()
	if len(args) == 0 {
		log.Fatal("no arguments passed")
	}
}

// walker implements filepath.WalkFunc.
func walker(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}
	//log.Printf("checking %s\n", path)
	for _, arg := range args {
		//if !strings.Contains(strings.ToLower(arg), strings.ToLower(path)){
		if !strings.Contains(strings.ToLower(path), strings.ToLower(arg)) {
			return nil
		}
	}
	fmt.Println(path)
	return nil
}

func main() {
	filepath.Walk(path, walker)
}
<commit_msg>cleanup<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var path string // path to search
var args []string

// isDir accepts a string (file path) and returns
// a boolean which indicates if the path is
// a valid directory.
func isDir(path string) bool {
	stat, err := os.Stat(path)
	if err != nil {
		log.Fatal(err)
	}
	return stat.IsDir()
}

func init() {
	// Set up command-line flags.
	flag.StringVar(&path, "p", ".", "path")
	flag.Parse()
	// Validate flags.
	if !isDir(path) {
		log.Fatal(path, "is not a valid path.")
	}
	args = flag.Args()
	if len(args) == 0 {
		log.Fatal("no arguments passed")
	}
}

// walker implements filepath.WalkFunc.
func walker(path string, info os.FileInfo, err error) error {
	if err != nil {
		log.Println(err)
	}
	for _, arg := range args {
		if !strings.Contains(strings.ToLower(info.Name()), strings.ToLower(arg)) {
			return nil
		}
	}
	fmt.Println(path)
	return nil
}

func main() {
	filepath.Walk(path, walker)
}
<|endoftext|>