<commit_before>/*

Writer implementation.

*/

package bitio

import (
	"bufio"
	"io"
)

// An io.Writer and io.ByteWriter at the same time.
type writerAndByteWriter interface {
	io.Writer
	io.ByteWriter
}

// Writer is the bit writer implementation.
//
// For convenience, it also implements io.WriterCloser and io.ByteWriter.
type Writer struct {
	out       writerAndByteWriter
	wrapperbw *bufio.Writer // wrapper bufio.Writer if the target does not implement io.ByteWriter
	cache     byte          // unwritten bits are stored here
	bits      byte          // number of unwritten bits in cache

	// TryError holds the first error occurred in TryXXX() methods.
	TryError error
}

// NewWriter returns a new Writer using the specified io.Writer as the output.
//
// Must be closed in order to flush cached data.
// If you can't or don't want to close it, flushing data can also be forced
// by calling Align().
func NewWriter(out io.Writer) *Writer {
	w := &Writer{}
	var ok bool
	w.out, ok = out.(writerAndByteWriter)
	if !ok {
		w.wrapperbw = bufio.NewWriter(out)
		w.out = w.wrapperbw
	}
	return w
}

// Write writes len(p) bytes (8 * len(p) bits) to the underlying writer.
//
// Write implements io.Writer, and gives a byte-level interface to the bit stream.
// This will give best performance if the underlying io.Writer is aligned
// to a byte boundary (else all the individual bytes are spread to multiple bytes).
// Byte boundary can be ensured by calling Align().
func (w *Writer) Write(p []byte) (n int, err error) {
	// w.bits will be the same after writing 8 bits, so we don't need to update that.
	if w.bits == 0 {
		return w.out.Write(p)
	}

	for i, b := range p {
		if err = w.writeUnalignedByte(b); err != nil {
			return i, err
		}
	}

	return len(p), nil
}

// WriteBits writes out the n lowest bits of r.
// Bits of r in positions higher than n are ignored.
//
// For example:
//   err := w.WriteBits(0x1234, 8) // bits higher than the 8th are ignored here
//
// is equivalent to:
//   err := w.WriteBits(0x34, 8)
func (w *Writer) WriteBits(r uint64, n uint8) (err error) {
	// if r would have bits set higher than n-1 (zero indexed),
	// WriteBitsUnsafe's implementation could "corrupt" bits in cache.
	// That is not acceptable. To be on the safe side, mask out higher bits:
	return w.WriteBitsUnsafe((r & (1<<n - 1)), n)
}

// WriteBitsUnsafe writes out the n lowest bits of r.
//
// r must not have bits set at positions higher than n-1 (zero indexed).
// If r might not satisfy this, a mask must be explicitly applied
// before passing it to WriteBitsUnsafe(), or WriteBits() should be used instead.
// WriteBitsUnsafe() gives slightly better performance than WriteBits() because
// the input r is not masked. Calling WriteBitsUnsafe() with an r that does
// not satisfy this is undefined behavior (might corrupt previously written bits).
//
// E.g. if you want to write 8 bits:
//   err := w.WriteBitsUnsafe(0x34, 8)        // This is OK,
//                                            // 0x34 has no bits set higher than the 8th
//   err := w.WriteBitsUnsafe(0x1234&0xff, 8) // &0xff masks out bits higher than the 8th
//
// Or:
//   err := w.WriteBits(0x1234, 8) // bits higher than the 8th are ignored here
func (w *Writer) WriteBitsUnsafe(r uint64, n uint8) (err error) {
	// Some optimization, frequent cases
	newbits := w.bits + n
	if newbits < 8 {
		// r fits into cache, no write will occur to out
		w.cache |= byte(r) << (8 - newbits)
		w.bits = newbits
		return nil
	}

	if newbits > 8 {
		// cache will be filled, and there will be more bits to write
		// "Fill cache" and write it out
		free := 8 - w.bits
		err = w.out.WriteByte(w.cache | byte(r>>(n-free)))
		if err != nil {
			return
		}
		n -= free
		// write out whole bytes
		for n >= 8 {
			n -= 8
			// No need to mask r, converting to byte will mask out higher bits
			err = w.out.WriteByte(byte(r >> n))
			if err != nil {
				return
			}
		}
		// Put remaining into cache
		if n > 0 {
			// Note: n < 8 (in case of n=8, 1<<n would overflow byte)
			w.cache, w.bits = (byte(r)&((1<<n)-1))<<(8-n), n
		} else {
			w.cache, w.bits = 0, 0
		}
		return nil
	}

	// cache will be filled exactly with the bits to be written
	bb := w.cache | byte(r)
	w.cache, w.bits = 0, 0
	return w.out.WriteByte(bb)
}

// WriteByte writes 8 bits.
//
// WriteByte implements io.ByteWriter.
func (w *Writer) WriteByte(b byte) (err error) {
	// w.bits will be the same after writing 8 bits, so we don't need to update that.
	if w.bits == 0 {
		return w.out.WriteByte(b)
	}
	return w.writeUnalignedByte(b)
}

// writeUnalignedByte writes 8 bits which are (may be) unaligned.
func (w *Writer) writeUnalignedByte(b byte) (err error) {
	// w.bits will be the same after writing 8 bits, so we don't need to update that.
	bits := w.bits
	err = w.out.WriteByte(w.cache | b>>bits)
	if err != nil {
		return
	}
	w.cache = (b & (1<<bits - 1)) << (8 - bits)
	return
}

// WriteBool writes one bit: 1 if param is true, 0 otherwise.
func (w *Writer) WriteBool(b bool) (err error) {
	if w.bits == 7 {
		if b {
			err = w.out.WriteByte(w.cache | 1)
		} else {
			err = w.out.WriteByte(w.cache)
		}
		if err != nil {
			return
		}
		w.cache, w.bits = 0, 0
		return nil
	}

	w.bits++
	if b {
		w.cache |= 1 << (8 - w.bits)
	}
	return nil
}

// Align aligns the bit stream to a byte boundary,
// so next write will start/go into a new byte.
// If there are cached bits, they are first written to the output.
// Returns the number of skipped (unset but still written) bits.
func (w *Writer) Align() (skipped uint8, err error) {
	if w.bits > 0 {
		if err = w.out.WriteByte(w.cache); err != nil {
			return
		}

		skipped = 8 - w.bits
		w.cache, w.bits = 0, 0
	}
	if w.wrapperbw != nil {
		err = w.wrapperbw.Flush()
	}
	return
}

// TryWrite tries to write len(p) bytes (8 * len(p) bits) to the underlying writer.
//
// If there was a previous TryError, it does nothing. Else it calls Write(),
// returns the data it provides and stores the error in the TryError field.
func (w *Writer) TryWrite(p []byte) (n int) {
	if w.TryError == nil {
		n, w.TryError = w.Write(p)
	}
	return
}

// TryWriteBits tries to write out the n lowest bits of r.
//
// If there was a previous TryError, it does nothing. Else it calls WriteBits(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteBits(r uint64, n uint8) {
	if w.TryError == nil {
		w.TryError = w.WriteBits(r, n)
	}
}

// TryWriteBitsUnsafe tries to write out the n lowest bits of r.
//
// If there was a previous TryError, it does nothing. Else it calls WriteBitsUnsafe(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteBitsUnsafe(r uint64, n uint8) {
	if w.TryError == nil {
		w.TryError = w.WriteBitsUnsafe(r, n)
	}
}

// TryWriteByte tries to write 8 bits.
//
// If there was a previous TryError, it does nothing. Else it calls WriteByte(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteByte(b byte) {
	if w.TryError == nil {
		w.TryError = w.WriteByte(b)
	}
}

// TryWriteBool tries to write one bit: 1 if param is true, 0 otherwise.
//
// If there was a previous TryError, it does nothing. Else it calls WriteBool(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteBool(b bool) {
	if w.TryError == nil {
		w.TryError = w.WriteBool(b)
	}
}

// TryAlign tries to align the bit stream to a byte boundary.
//
// If there was a previous TryError, it does nothing. Else it calls Align(),
// returns the data it provides and stores the error in the TryError field.
func (w *Writer) TryAlign() (skipped uint8) {
	if w.TryError == nil {
		skipped, w.TryError = w.Align()
	}
	return
}

// Close closes the bit writer, writes out cached bits.
// It does not close the underlying io.Writer.
//
// Close implements io.Closer.
func (w *Writer) Close() (err error) {
	// Make sure cached bits are flushed:
	if _, err = w.Align(); err != nil {
		return
	}

	return nil
}
<commit_msg>Improve docs<commit_after>/*

Writer implementation.

*/

package bitio

import (
	"bufio"
	"io"
)

// An io.Writer and io.ByteWriter at the same time.
type writerAndByteWriter interface {
	io.Writer
	io.ByteWriter
}

// Writer is the bit writer implementation.
//
// For convenience, it also implements io.WriterCloser and io.ByteWriter.
type Writer struct {
	out       writerAndByteWriter
	wrapperbw *bufio.Writer // wrapper bufio.Writer if the target does not implement io.ByteWriter
	cache     byte          // unwritten bits are stored here
	bits      byte          // number of unwritten bits in cache

	// TryError holds the first error occurred in TryXXX() methods.
	TryError error
}

// NewWriter returns a new Writer using the specified io.Writer as the output.
//
// Must be closed in order to flush cached data.
// If you can't or don't want to close it, flushing data can also be forced
// by calling Align().
func NewWriter(out io.Writer) *Writer {
	w := &Writer{}
	var ok bool
	w.out, ok = out.(writerAndByteWriter)
	if !ok {
		w.wrapperbw = bufio.NewWriter(out)
		w.out = w.wrapperbw
	}
	return w
}

// Write writes len(p) bytes (8 * len(p) bits) to the underlying writer.
//
// Write implements io.Writer, and gives a byte-level interface to the bit stream.
// This will give best performance if the underlying io.Writer is aligned
// to a byte boundary (else all the individual bytes are spread to multiple bytes).
// Byte boundary can be ensured by calling Align().
func (w *Writer) Write(p []byte) (n int, err error) {
	// w.bits will be the same after writing 8 bits, so we don't need to update that.
	if w.bits == 0 {
		return w.out.Write(p)
	}

	for i, b := range p {
		if err = w.writeUnalignedByte(b); err != nil {
			return i, err
		}
	}

	return len(p), nil
}

// WriteBits writes out the n lowest bits of r.
// Bits of r in positions higher than n are ignored.
//
// For example:
//   err := w.WriteBits(0x1234, 8)
//
// is equivalent to:
//   err := w.WriteBits(0x34, 8)
func (w *Writer) WriteBits(r uint64, n uint8) (err error) {
	// if r would have bits set at n or higher positions (zero indexed),
	// WriteBitsUnsafe's implementation could "corrupt" bits in cache.
	// That is not acceptable. To be on the safe side, mask out higher bits:
	return w.WriteBitsUnsafe((r & (1<<n - 1)), n)
}

// WriteBitsUnsafe writes out the n lowest bits of r.
//
// r must not have bits set at n or higher positions (zero indexed).
// If r might not satisfy this, a mask must be explicitly applied
// before passing it to WriteBitsUnsafe(), or WriteBits() should be used instead.
//
// WriteBitsUnsafe() offers slightly better performance than WriteBits() because
// the input r is not masked. Calling WriteBitsUnsafe() with an r that does
// not satisfy this is undefined behavior (might corrupt previously written bits).
//
// E.g. if you want to write 8 bits:
//   err := w.WriteBitsUnsafe(0x34, 8)        // This is OK,
//                                            // 0x34 has no bits set higher than the 8th
//   err := w.WriteBitsUnsafe(0x1234&0xff, 8) // &0xff masks out bits higher than the 8th
//
// Or:
//   err := w.WriteBits(0x1234, 8)            // bits higher than the 8th are ignored here
func (w *Writer) WriteBitsUnsafe(r uint64, n uint8) (err error) {
	// Some optimization, frequent cases
	newbits := w.bits + n
	if newbits < 8 {
		// r fits into cache, no write will occur to out
		w.cache |= byte(r) << (8 - newbits)
		w.bits = newbits
		return nil
	}

	if newbits > 8 {
		// cache will be filled, and there will be more bits to write
		// "Fill cache" and write it out
		free := 8 - w.bits
		err = w.out.WriteByte(w.cache | byte(r>>(n-free)))
		if err != nil {
			return
		}
		n -= free
		// write out whole bytes
		for n >= 8 {
			n -= 8
			// No need to mask r, converting to byte will mask out higher bits
			err = w.out.WriteByte(byte(r >> n))
			if err != nil {
				return
			}
		}
		// Put remaining into cache
		if n > 0 {
			// Note: n < 8 (in case of n=8, 1<<n would overflow byte)
			w.cache, w.bits = (byte(r)&((1<<n)-1))<<(8-n), n
		} else {
			w.cache, w.bits = 0, 0
		}
		return nil
	}

	// cache will be filled exactly with the bits to be written
	bb := w.cache | byte(r)
	w.cache, w.bits = 0, 0
	return w.out.WriteByte(bb)
}

// WriteByte writes 8 bits.
//
// WriteByte implements io.ByteWriter.
func (w *Writer) WriteByte(b byte) (err error) {
	// w.bits will be the same after writing 8 bits, so we don't need to update that.
	if w.bits == 0 {
		return w.out.WriteByte(b)
	}
	return w.writeUnalignedByte(b)
}

// writeUnalignedByte writes 8 bits which are (may be) unaligned.
func (w *Writer) writeUnalignedByte(b byte) (err error) {
	// w.bits will be the same after writing 8 bits, so we don't need to update that.
	bits := w.bits
	err = w.out.WriteByte(w.cache | b>>bits)
	if err != nil {
		return
	}
	w.cache = (b & (1<<bits - 1)) << (8 - bits)
	return
}

// WriteBool writes one bit: 1 if param is true, 0 otherwise.
func (w *Writer) WriteBool(b bool) (err error) {
	if w.bits == 7 {
		if b {
			err = w.out.WriteByte(w.cache | 1)
		} else {
			err = w.out.WriteByte(w.cache)
		}
		if err != nil {
			return
		}
		w.cache, w.bits = 0, 0
		return nil
	}

	w.bits++
	if b {
		w.cache |= 1 << (8 - w.bits)
	}
	return nil
}

// Align aligns the bit stream to a byte boundary,
// so next write will start/go into a new byte.
// If there are cached bits, they are first written to the output.
// Returns the number of skipped (unset but still written) bits.
func (w *Writer) Align() (skipped uint8, err error) {
	if w.bits > 0 {
		if err = w.out.WriteByte(w.cache); err != nil {
			return
		}

		skipped = 8 - w.bits
		w.cache, w.bits = 0, 0
	}
	if w.wrapperbw != nil {
		err = w.wrapperbw.Flush()
	}
	return
}

// TryWrite tries to write len(p) bytes (8 * len(p) bits) to the underlying writer.
//
// If there was a previous TryError, it does nothing. Else it calls Write(),
// returns the data it provides and stores the error in the TryError field.
func (w *Writer) TryWrite(p []byte) (n int) {
	if w.TryError == nil {
		n, w.TryError = w.Write(p)
	}
	return
}

// TryWriteBits tries to write out the n lowest bits of r.
//
// If there was a previous TryError, it does nothing. Else it calls WriteBits(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteBits(r uint64, n uint8) {
	if w.TryError == nil {
		w.TryError = w.WriteBits(r, n)
	}
}

// TryWriteBitsUnsafe tries to write out the n lowest bits of r.
//
// If there was a previous TryError, it does nothing. Else it calls WriteBitsUnsafe(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteBitsUnsafe(r uint64, n uint8) {
	if w.TryError == nil {
		w.TryError = w.WriteBitsUnsafe(r, n)
	}
}

// TryWriteByte tries to write 8 bits.
//
// If there was a previous TryError, it does nothing. Else it calls WriteByte(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteByte(b byte) {
	if w.TryError == nil {
		w.TryError = w.WriteByte(b)
	}
}

// TryWriteBool tries to write one bit: 1 if param is true, 0 otherwise.
//
// If there was a previous TryError, it does nothing. Else it calls WriteBool(),
// and stores the error in the TryError field.
func (w *Writer) TryWriteBool(b bool) {
	if w.TryError == nil {
		w.TryError = w.WriteBool(b)
	}
}

// TryAlign tries to align the bit stream to a byte boundary.
//
// If there was a previous TryError, it does nothing. Else it calls Align(),
// returns the data it provides and stores the error in the TryError field.
func (w *Writer) TryAlign() (skipped uint8) {
	if w.TryError == nil {
		skipped, w.TryError = w.Align()
	}
	return
}

// Close closes the bit writer, writes out cached bits.
// It does not close the underlying io.Writer.
//
// Close implements io.Closer.
func (w *Writer) Close() (err error) {
	// Make sure cached bits are flushed:
	if _, err = w.Align(); err != nil {
		return
	}

	return nil
}
<|endoftext|>


<commit_before>package rancher

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher-metadata/metadata"
	"time"
)

const (
	RETRY_INTERVAL = 5 * time.Second
	RETRY_MAX      = 20

	RANCHER_METADATA_URL = "http://rancher-metadata"
)

var (
	log = logrus.WithFields(logrus.Fields{"pkg": "rancher"})
)

func GetIPsForServiceInStack(serviceName, stackName string) ([]string, error) {
	handler := metadata.NewHandler(RANCHER_METADATA_URL)
	containerName := ""
	for i := 0; i < RETRY_MAX; i++ {
		log.Debugf("Try to connect to Rancher metadata at %v", RANCHER_METADATA_URL)
		container, err := handler.GetSelfContainer()
		if err == nil {
			containerName = container.Name
			break
		}
		log.Debugf("Connection error %v. Retrying", err.Error())
		time.Sleep(RETRY_INTERVAL)
	}
	if containerName == "" {
		return nil, fmt.Errorf("Rancher metadata service return empty for container name")
	}
	log.Debugf("Got Rancher metadata at %v, Convoy container name %v", RANCHER_METADATA_URL, containerName)

	containers, err := handler.GetContainers()
	if err != nil {
		return nil, err
	}
	ips := []string{}
	for _, container := range containers {
		if container.StackName == stackName && container.ServiceName == serviceName {
			if container.PrimaryIp != "" {
				ips = append(ips, container.PrimaryIp)
			}
		}
	}
	if len(ips) == 0 {
		return nil, fmt.Errorf("Cannot find containers with stack %v service %v", stackName, serviceName)
	}
	return ips, nil
}
<commit_msg>rancher: Use new wait mechanism of rancher-metadata<commit_after>package rancher

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher-metadata/metadata"
	"time"
)

const (
	RETRY_INTERVAL = 5 * time.Second
	RETRY_MAX      = 20

	RANCHER_METADATA_URL = "http://rancher-metadata/latest"
)

var (
	log = logrus.WithFields(logrus.Fields{"pkg": "rancher"})
)

func GetIPsForServiceInStack(serviceName, stackName string) ([]string, error) {
	log.Debugf("Try to connect to Rancher metadata at %v", RANCHER_METADATA_URL)
	client, err := metadata.NewClientAndWait(RANCHER_METADATA_URL)
	if err != nil {
		return nil, err
	}
	log.Debugf("Got Rancher metadata at %v", RANCHER_METADATA_URL)

	containers, err := client.GetContainers()
	if err != nil {
		return nil, err
	}
	ips := []string{}
	for _, container := range containers {
		if container.StackName == stackName && container.ServiceName == serviceName {
			if container.PrimaryIp != "" {
				ips = append(ips, container.PrimaryIp)
			}
		}
	}
	if len(ips) == 0 {
		return nil, fmt.Errorf("Cannot find containers with stack %v service %v", stackName, serviceName)
	}
	return ips, nil
}
<|endoftext|>


<commit_before>package view

import (
	"golang.org/x/image/colornames"
	"gomatcha.io/matcha/bridge"
	"gomatcha.io/matcha/layout/constraint"
	"gomatcha.io/matcha/paint"
	"gomatcha.io/matcha/view"
)

func init() {
	bridge.RegisterFunc("gomatcha.io/matcha/examples/view NewSlider", func() view.View {
		return NewSlider()
	})
}

type Slider struct {
	view.Embed
	value float64
}

func NewSlider() *Slider {
	return &Slider{
		value: 0.5,
	}
}

func (v *Slider) Build(ctx view.Context) view.Model {
	l := &constraint.Layouter{}

	chl1 := view.NewSlider()
	chl1.MinValue = -5
	chl1.MaxValue = 5
	chl1.Value = v.value
	chl1.PaintStyle = &paint.Style{BackgroundColor: colornames.Green}
	chl1.OnChange = func(value float64) {
		v.value = value
		v.Signal()
		fmt.Println("onValueChange", value)
	}
	chl1.OnSubmit = func(value float64) {
		fmt.Println("onSubmit", value)
	}
	g1 := l.Add(chl1, func(s *constraint.Solver) {
		s.Top(100)
		s.Left(100)
		s.Width(200)
	})

	chl2 := view.NewSlider()
	chl2.Value = v.value
	chl2.MinValue = -10
	chl2.MaxValue = 10
	chl2.Enabled = false
	chl2.OnChange = func(value float64) {
		fmt.Println("onValueChange2", value)
	}
	l.Add(chl2, func(s *constraint.Solver) {
		s.TopEqual(g1.Bottom().Add(50))
		s.LeftEqual(g1.Left())
		s.WidthEqual(g1.Width())
	})

	return view.Model{
		Children: l.Views(),
		Layouter: l,
		Painter:  &paint.Style{BackgroundColor: colornames.White},
	}
}
<commit_msg>Add missing import<commit_after>package view

import (
	"fmt"

	"golang.org/x/image/colornames"
	"gomatcha.io/matcha/bridge"
	"gomatcha.io/matcha/layout/constraint"
	"gomatcha.io/matcha/paint"
	"gomatcha.io/matcha/view"
)

func init() {
	bridge.RegisterFunc("gomatcha.io/matcha/examples/view NewSlider", func() view.View {
		return NewSlider()
	})
}

type Slider struct {
	view.Embed
	value float64
}

func NewSlider() *Slider {
	return &Slider{
		value: 0.5,
	}
}

func (v *Slider) Build(ctx view.Context) view.Model {
	l := &constraint.Layouter{}

	chl1 := view.NewSlider()
	chl1.MinValue = -5
	chl1.MaxValue = 5
	chl1.Value = v.value
	chl1.PaintStyle = &paint.Style{BackgroundColor: colornames.Green}
	chl1.OnChange = func(value float64) {
		v.value = value
		v.Signal()
		fmt.Println("onValueChange", value)
	}
	chl1.OnSubmit = func(value float64) {
		fmt.Println("onSubmit", value)
	}
	g1 := l.Add(chl1, func(s *constraint.Solver) {
		s.Top(100)
		s.Left(100)
		s.Width(200)
	})

	chl2 := view.NewSlider()
	chl2.Value = v.value
	chl2.MinValue = -10
	chl2.MaxValue = 10
	chl2.Enabled = false
	chl2.OnChange = func(value float64) {
		fmt.Println("onValueChange2", value)
	}
	l.Add(chl2, func(s *constraint.Solver) {
		s.TopEqual(g1.Bottom().Add(50))
		s.LeftEqual(g1.Left())
		s.WidthEqual(g1.Width())
	})

	return view.Model{
		Children: l.Views(),
		Layouter: l,
		Painter:  &paint.Style{BackgroundColor: colornames.White},
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Benoît Amiaux. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package iobit

import (
	"encoding/binary"
	"errors"
)

// Writer wraps a raw byte array and provides multiple methoods to write data bit-by-bit
// Its methods don't return the usual error as it is too expensive.
// Instead, write errors can be checked with the Flush() method.
type Writer struct {
	dst   []byte
	cache uint64
	fill  uint
	idx   int
}

var (
	ErrOverflow  = errors.New("bit overflow")
	ErrUnderflow = errors.New("bit underflow")
)

// NewWriter returns a new writer writing to <dst> byte array.
func NewWriter(dst []byte) *Writer {
	return &Writer{dst: dst}
}

// PutUint32 writes up to 32 <bits> from <val> in big-endian order.
func (w *Writer) PutUint32(bits uint, val uint32) {
	u := uint64(val)
	// manually inlined until compiler improves
	if w.fill+bits > 64 {
		if w.idx+4 <= len(w.dst) {
			binary.BigEndian.PutUint32(w.dst[w.idx:], uint32(w.cache>>32))
		}
		w.idx += 4
		w.cache <<= 32
		w.fill -= 32
	}
	u &= ^(^uint64(0) << bits)
	u <<= 64 - w.fill - bits
	w.fill += bits
	w.cache |= u
}

// PutUint32Le writes up to 32 <bits> from <val> in little-endian order.
func (w *Writer) PutUint32Le(bits uint, val uint32) {
	val = bswap32(val)
	left, right := bits&7, bits&0xF8
	sub := val >> (24 - right)
	// manually inlined until compiler improves
	if w.fill+bits > 64 {
		if w.idx+4 <= len(w.dst) {
			binary.BigEndian.PutUint32(w.dst[w.idx:], uint32(w.cache>>32))
		}
		w.idx += 4
		w.cache <<= 32
		w.fill -= 32
	}
	mask := ^uint32(0) << left
	sub &= ^mask
	val >>= 32 - bits
	val &= mask
	u := uint64(val + sub)
	u <<= 64 - w.fill - bits
	w.fill += bits
	w.cache |= u
}

// PutUint64 writes up to 64 <bits> from <val> in big-endian order.
func (w *Writer) PutUint64(bits uint, val uint64) {
	if bits > 32 {
		w.PutUint32(bits-32, uint32(val>>32))
		bits = 32
		val &= 0xFFFFFFFF
	}
	w.PutUint32(bits, uint32(val))
}

// PutUint64Le writes up to 64 <bits> from <val> in little-endian order.
func (w *Writer) PutUint64Le(bits uint, val uint64) {
	if bits > 32 {
		w.PutUint32Le(32, uint32(val&0xFFFFFFFF))
		bits -= 32
		val >>= 32
	}
	w.PutUint32Le(bits, uint32(val))
}

// PutBit writes one bit to output.
func (w *Writer) PutBit(val bool) {
	v := uint32(0)
	if val {
		v = 1
	}
	w.PutUint32(1, v)
}

// PutByte writes one byte.
func (w *Writer) PutByte(val byte) {
	w.PutUint32(8, uint32(val))
}

// PutLe16 writes 16 bits in little-endian order.
func (w *Writer) PutLe16(val uint16) {
	w.PutUint32Le(16, uint32(val))
}

// PutBe16 writes 16 bits in big-endian order.
func (w *Writer) PutBe16(val uint16) {
	w.PutUint32(16, uint32(val))
}

// PutLe32 writes 32 bits in little-endian order.
func (w *Writer) PutLe32(val uint32) {
	w.PutUint32Le(32, val)
}

// PutBe32 writes 32 bits in big-endian order.
func (w *Writer) PutBe32(val uint32) {
	w.PutUint32(32, val)
}

// PutLe64 writes 64 bits in little-endian order.
func (w *Writer) PutLe64(val uint64) {
	w.PutUint64Le(64, val)
}

// PutBe64 writes 64 bits in big-endian order.
func (w *Writer) PutBe64(val uint64) {
	w.PutUint64(64, val)
}

// PutUint8 writes up to 8 bits.
func (w *Writer) PutUint8(bits uint, val byte) {
	w.PutUint32(bits, uint32(val))
}

// PutInt8 writes up to 8 signed bits.
func (w *Writer) PutInt8(bits uint, val int8) {
	w.PutUint32(bits, uint32(val))
}

// PutUint16 writes up to 16 bits in big-endian order.
func (w *Writer) PutUint16(bits uint, val uint16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt16 writes up to 16 signed bits in big-endian order.
func (w *Writer) PutInt16(bits uint, val int16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt32 writes up to 32 signed bits in big-endian order.
func (w *Writer) PutInt32(bits uint, val int32) {
	w.PutUint32(bits, uint32(val))
}

// PutInt64 writes up to 64 signed bits in big-endian order.
func (w *Writer) PutInt64(bits uint, val int64) {
	w.PutUint64(bits, uint64(val))
}

// Flush flushes the writer to its underlying buffer.
// Returns ErrUnderflow if the output is not byte-aligned.
// Returns ErrOverflow if the output array is too small.
func (w *Writer) Flush() error {
	for w.fill >= 8 && w.idx < len(w.dst) {
		w.dst[w.idx] = byte(w.cache >> 56)
		w.idx += 1
		w.cache <<= 8
		w.fill -= 8
	}
	if w.idx+int(w.fill) > len(w.dst) {
		return ErrOverflow
	}
	if w.fill != 0 {
		return ErrUnderflow
	}
	return nil
}

// Write writes a whole slice <p> at once.
// Returns an error if the writer is not byte-aligned.
func (w *Writer) Write(p []byte) (int, error) {
	err := w.Flush()
	if err != nil {
		return 0, err
	}
	n := 0
	if w.idx < len(w.dst) {
		n = copy(w.dst[w.idx:], p)
	}
	w.idx += len(p)
	if n != len(p) {
		return n, ErrOverflow
	}
	return n, nil
}

// Index returns the current writer position in bits.
func (w *Writer) Index() int {
	return w.idx<<3 + int(w.fill)
}

func imin(a, b int) int {
	if a > b {
		return b
	}
	return a
}

// Bits returns the number of bits available to write.
func (w *Writer) Bits() int {
	size := len(w.dst)
	return size<<3 - imin(w.idx<<3+int(w.fill), size<<3)
}

// Bytes returns a byte array of what's left to write.
// Note that this array is 8-bit aligned even if the writer is not.
func (w *Writer) Bytes() []byte {
	skip := w.idx + int(w.fill>>3)
	if skip >= len(w.dst) {
		return w.dst[:0]
	}
	return w.dst[skip:len(w.dst)]
}

// Reset resets the writer to its initial position.
func (w *Writer) Reset() {
	w.fill = 0
	w.idx = 0
}
<commit_msg>optimize PutLeNN functions by using bswap<commit_after>// Copyright 2013 Benoît Amiaux. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package iobit

import (
	"encoding/binary"
	"errors"
)

// Writer wraps a raw byte array and provides multiple methoods to write data bit-by-bit
// Its methods don't return the usual error as it is too expensive.
// Instead, write errors can be checked with the Flush() method.
type Writer struct {
	dst   []byte
	cache uint64
	fill  uint
	idx   int
}

var (
	ErrOverflow  = errors.New("bit overflow")
	ErrUnderflow = errors.New("bit underflow")
)

// NewWriter returns a new writer writing to <dst> byte array.
func NewWriter(dst []byte) *Writer {
	return &Writer{dst: dst}
}

// PutUint32 writes up to 32 <bits> from <val> in big-endian order.
func (w *Writer) PutUint32(bits uint, val uint32) {
	u := uint64(val)
	// manually inlined until compiler improves
	if w.fill+bits > 64 {
		if w.idx+4 <= len(w.dst) {
			binary.BigEndian.PutUint32(w.dst[w.idx:], uint32(w.cache>>32))
		}
		w.idx += 4
		w.cache <<= 32
		w.fill -= 32
	}
	u &= ^(^uint64(0) << bits)
	u <<= 64 - w.fill - bits
	w.fill += bits
	w.cache |= u
}

// PutUint32Le writes up to 32 <bits> from <val> in little-endian order.
func (w *Writer) PutUint32Le(bits uint, val uint32) {
	val = bswap32(val)
	left, right := bits&7, bits&0xF8
	sub := val >> (24 - right)
	// manually inlined until compiler improves
	if w.fill+bits > 64 {
		if w.idx+4 <= len(w.dst) {
			binary.BigEndian.PutUint32(w.dst[w.idx:], uint32(w.cache>>32))
		}
		w.idx += 4
		w.cache <<= 32
		w.fill -= 32
	}
	mask := ^uint32(0) << left
	sub &= ^mask
	val >>= 32 - bits
	val &= mask
	u := uint64(val + sub)
	u <<= 64 - w.fill - bits
	w.fill += bits
	w.cache |= u
}

// PutUint64 writes up to 64 <bits> from <val> in big-endian order.
func (w *Writer) PutUint64(bits uint, val uint64) {
	if bits > 32 {
		w.PutUint32(bits-32, uint32(val>>32))
		bits = 32
		val &= 0xFFFFFFFF
	}
	w.PutUint32(bits, uint32(val))
}

// PutUint64Le writes up to 64 <bits> from <val> in little-endian order.
func (w *Writer) PutUint64Le(bits uint, val uint64) {
	if bits > 32 {
		w.PutUint32Le(32, uint32(val&0xFFFFFFFF))
		bits -= 32
		val >>= 32
	}
	w.PutUint32Le(bits, uint32(val))
}

// PutBit writes one bit to output.
func (w *Writer) PutBit(val bool) {
	v := uint32(0)
	if val {
		v = 1
	}
	w.PutUint32(1, v)
}

// PutByte writes one byte.
func (w *Writer) PutByte(val byte) {
	w.PutUint32(8, uint32(val))
}

// PutLe16 writes 16 bits in little-endian order.
func (w *Writer) PutLe16(val uint16) {
	w.PutUint32(16, uint32(bswap16(val)))
}

// PutBe16 writes 16 bits in big-endian order.
func (w *Writer) PutBe16(val uint16) {
	w.PutUint32(16, uint32(val))
}

// PutLe32 writes 32 bits in little-endian order.
func (w *Writer) PutLe32(val uint32) {
	w.PutUint32(32, bswap32(val))
}

// PutBe32 writes 32 bits in big-endian order.
func (w *Writer) PutBe32(val uint32) {
	w.PutUint32(32, val)
}

// PutLe64 writes 64 bits in little-endian order.
func (w *Writer) PutLe64(val uint64) {
	w.PutLe32(uint32(val & 0xFFFFFFFF))
	w.PutLe32(uint32(val >> 32 & 0xFFFFFFFF))
}

// PutBe64 writes 64 bits in big-endian order.
func (w *Writer) PutBe64(val uint64) {
	w.PutUint64(64, val)
}

// PutUint8 writes up to 8 bits.
func (w *Writer) PutUint8(bits uint, val byte) {
	w.PutUint32(bits, uint32(val))
}

// PutInt8 writes up to 8 signed bits.
func (w *Writer) PutInt8(bits uint, val int8) {
	w.PutUint32(bits, uint32(val))
}

// PutUint16 writes up to 16 bits in big-endian order.
func (w *Writer) PutUint16(bits uint, val uint16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt16 writes up to 16 signed bits in big-endian order.
func (w *Writer) PutInt16(bits uint, val int16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt32 writes up to 32 signed bits in big-endian order.
func (w *Writer) PutInt32(bits uint, val int32) {
	w.PutUint32(bits, uint32(val))
}

// PutInt64 writes up to 64 signed bits in big-endian order.
func (w *Writer) PutInt64(bits uint, val int64) {
	w.PutUint64(bits, uint64(val))
}

// Flush flushes the writer to its underlying buffer.
// Returns ErrUnderflow if the output is not byte-aligned.
// Returns ErrOverflow if the output array is too small.
func (w *Writer) Flush() error {
	for w.fill >= 8 && w.idx < len(w.dst) {
		w.dst[w.idx] = byte(w.cache >> 56)
		w.idx += 1
		w.cache <<= 8
		w.fill -= 8
	}
	if w.idx+int(w.fill) > len(w.dst) {
		return ErrOverflow
	}
	if w.fill != 0 {
		return ErrUnderflow
	}
	return nil
}

// Write writes a whole slice <p> at once.
// Returns an error if the writer is not byte-aligned.
func (w *Writer) Write(p []byte) (int, error) {
	err := w.Flush()
	if err != nil {
		return 0, err
	}
	n := 0
	if w.idx < len(w.dst) {
		n = copy(w.dst[w.idx:], p)
	}
	w.idx += len(p)
	if n != len(p) {
		return n, ErrOverflow
	}
	return n, nil
}

// Index returns the current writer position in bits.
func (w *Writer) Index() int {
	return w.idx<<3 + int(w.fill)
}

func imin(a, b int) int {
	if a > b {
		return b
	}
	return a
}

// Bits returns the number of bits available to write.
func (w *Writer) Bits() int {
	size := len(w.dst)
	return size<<3 - imin(w.idx<<3+int(w.fill), size<<3)
}

// Bytes returns a byte array of what's left to write.
// Note that this array is 8-bit aligned even if the writer is not.
func (w *Writer) Bytes() []byte {
	skip := w.idx + int(w.fill>>3)
	if skip >= len(w.dst) {
		return w.dst[:0]
	}
	return w.dst[skip:len(w.dst)]
}

// Reset resets the writer to its initial position.
func (w *Writer) Reset() {
	w.fill = 0
	w.idx = 0
}
<|endoftext|>


<commit_before>package uilive

import (
	"bytes"
	"errors"
	"io"
	"os"
	"sync"
	"time"
)

// ESC is the ASCII code for escape character
const ESC = 27

// RefreshInterval is the default refresh interval to update the ui
var RefreshInterval = time.Millisecond

// Out is the default output writer for the Writer
var Out = os.Stdout

// ErrClosedPipe is the error returned when trying to writer is not listening
var ErrClosedPipe = errors.New("uilive: read/write on closed pipe")

// FdWriter is a writer with a file descriptor.
type FdWriter interface {
	io.Writer
	Fd() uintptr
}

// Writer is a buffered the writer that updates the terminal. The contents of writer will be flushed on a timed interval or when Flush is called.
type Writer struct {
	// Out is the writer to write to
	Out io.Writer

	// RefreshInterval is the time the UI sould refresh
	RefreshInterval time.Duration

	// stopChan is buffered channel for stopping the listener
	stopChan chan struct{}

	// running is flag for determining if the listerner is running
	running bool

	buf       bytes.Buffer
	mtx       *sync.Mutex
	lineCount int
}

type bypass struct {
	writer *Writer
}

// New returns a new Writer with defaults
func New() *Writer {
	return &Writer{
		Out:             Out,
		RefreshInterval: RefreshInterval,

		mtx:      &sync.Mutex{},
		stopChan: make(chan struct{}),
	}
}

// Flush writes to the out and resets the buffer. It should be called after the last call to Write to ensure that any data buffered in the Writer is written to output.
// Any incomplete escape sequence at the end is considered complete for formatting purposes.
// An error is returned if the contents of the buffer cannot be written to the underlying output stream
func (w *Writer) Flush() error {
	w.mtx.Lock()
	defer w.mtx.Unlock()

	// do nothing is  buffer is empty
	if len(w.buf.Bytes()) == 0 {
		return nil
	}
	w.clearLines()

	lines := 0
	for _, b := range w.buf.Bytes() {
		if b == '\n' {
			lines++
		}
	}
	w.lineCount = lines
	_, err := w.Out.Write(w.buf.Bytes())
	w.buf.Reset()
	return err
}

// Start starts the listener in a non-blocking manner
func (w *Writer) Start() {
	go w.Listen()
}

// Stop stops the listener that updates the terminal
func (w *Writer) Stop() {
	w.Flush()
	close(w.stopChan)
}

// Listen listens for updates to the writer's buffer and flushes to the out provided. It blocks the runtime.
func (w *Writer) Listen() {
	if w.running {
		return
	}
	for {
		select {
		case <-w.stopChan:
			{
				w.running = false
				return
			}
		default:
			{
				w.Wait()
			}
		}
	}
}

// Wait waits for the writer to finish writing
func (w *Writer) Wait() {
	time.Sleep(w.RefreshInterval)
	w.Flush()
}

// Write save the contents of b to its buffers. The only errors returned are ones encountered while writing to the underlying buffer.
func (w *Writer) Write(b []byte) (n int, err error) {
	w.mtx.Lock()
	defer w.mtx.Unlock()
	return w.buf.Write(b)
}

// Bypass creates an io.Writer which allows non-buffered output to be written to the underlying output
func (w *Writer) Bypass() io.Writer {
	return &bypass{writer: w}
}

func (b *bypass) Write(p []byte) (n int, err error) {
	b.writer.mtx.Lock()
	defer b.writer.mtx.Unlock()

	b.writer.clearLines()
	b.writer.lineCount = 0
	return b.writer.Out.Write(p)
}
<commit_msg>Using time.Ticker for running stoppable listener. Fix edge case where flush happens after the listener is stopped.<commit_after>package uilive

import (
	"bytes"
	"errors"
	"io"
	"os"
	"sync"
	"time"
)

// ESC is the ASCII code for escape character
const ESC = 27

// RefreshInterval is the default refresh interval to update the ui
var RefreshInterval = time.Millisecond

// Out is the default output writer for the Writer
var Out = os.Stdout

// ErrClosedPipe is the error returned when trying to writer is not listening
var ErrClosedPipe = errors.New("uilive: read/write on closed pipe")

// FdWriter is a writer with a file descriptor.
type FdWriter interface {
	io.Writer
	Fd() uintptr
}

// Writer is a buffered the writer that updates the terminal. The contents of writer will be flushed on a timed interval or when Flush is called.
type Writer struct {
	// Out is the writer to write to
	Out io.Writer

	// RefreshInterval is the time the UI sould refresh
	RefreshInterval time.Duration

	ticker *time.Ticker

	buf       bytes.Buffer
	mtx       *sync.Mutex
	lineCount int
}

type bypass struct {
	writer *Writer
}

// New returns a new Writer with defaults
func New() *Writer {
	return &Writer{
		Out:             Out,
		RefreshInterval: RefreshInterval,

		mtx: &sync.Mutex{},
	}
}

// Flush writes to the out and resets the buffer. It should be called after the last call to Write to ensure that any data buffered in the Writer is written to output.
// Any incomplete escape sequence at the end is considered complete for formatting purposes.
// An error is returned if the contents of the buffer cannot be written to the underlying output stream
func (w *Writer) Flush() error {
	w.mtx.Lock()
	defer w.mtx.Unlock()

	// do nothing is  buffer is empty
	if len(w.buf.Bytes()) == 0 {
		return nil
	}
	w.clearLines()

	lines := 0
	for _, b := range w.buf.Bytes() {
		if b == '\n' {
			lines++
		}
	}
	w.lineCount = lines
	_, err := w.Out.Write(w.buf.Bytes())
	w.buf.Reset()
	return err
}

// Start starts the listener in a non-blocking manner
func (w *Writer) Start() {
	if w.ticker == nil {
		w.ticker = time.NewTicker(w.RefreshInterval)
	}

	go w.Listen()
}

// Stop stops the listener that updates the terminal
func (w *Writer) Stop() {
	w.Flush()
	w.ticker.Stop()
}

// Listen listens for updates to the writer's buffer and flushes to the out provided. It blocks the runtime.
func (w *Writer) Listen() {
	go func() {
		for _ = range w.ticker.C {
			w.Flush()
		}
	}()
}

// Write save the contents of b to its buffers. The only errors returned are ones encountered while writing to the underlying buffer.
func (w *Writer) Write(b []byte) (n int, err error) {
	w.mtx.Lock()
	defer w.mtx.Unlock()
	return w.buf.Write(b)
}

// Bypass creates an io.Writer which allows non-buffered output to be written to the underlying output
func (w *Writer) Bypass() io.Writer {
	return &bypass{writer: w}
}

func (b *bypass) Write(p []byte) (n int, err error) {
	b.writer.mtx.Lock()
	defer b.writer.mtx.Unlock()

	b.writer.clearLines()
	b.writer.lineCount = 0
	return b.writer.Out.Write(p)
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.net/websocket"
	"fmt"
	"io"
	"net/http"
	"os"
)

func indexHandler(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, `

`)
}

func startTail(file string, ch chan string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	fileInfo, err := f.Stat()
	if err != nil {
		return err
	}
	fileSize := fileInfo.Size()
	var bufSizeMax int64 = 1024
	var bufSize int64
	if fileSize > bufSizeMax {
		bufSize = bufSizeMax
	} else {
		bufSize = fileSize
	}
	go func() {
		fmt.Println("tail start")
		ch <- file
		buf := make([]byte, bufSize)
		var offset int64 = 0
		{
			n, err := f.ReadAt(buf, offset+bufSize)
			if err != nil && err != io.EOF {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			fmt.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		for {
			n, err := f.Read(buf)
			if err == io.EOF && n == 0 {
				continue
			}
			if err != nil {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			fmt.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		fmt.Println("tail end")
	}()
	return nil
}

func makeWebsocketHandlerWithChannel(ch chan string, f func(chan string, *websocket.Conn)) func(*websocket.Conn) {
	return func(ws *websocket.Conn) {
		f(ch, ws)
	}
}

type Data struct {
	Key   string
	Value string
}

func websocketTailHandler(ch chan string, ws *websocket.Conn) {
	fmt.Printf("tailHandler %v\n", ws)
	// send first line as file name
	fileName := <-ch
	if err := websocket.JSON.Send(ws, Data{"filename", fileName}); err != nil {
		fmt.Println("ERR:websoket.Message.Send(): " + err.Error())
	}
	for {
		line := <-ch
		if err := websocket.JSON.Send(ws, Data{"msg", line}); err != nil {
			fmt.Println("ERR:websoket.Message.Send(): " + err.Error())
		}
		fmt.Printf("tailHandler write[%v]\n", line)
	}
	fmt.Println("tailHandler finished")
}

// for debug
func pseudoSubscriber(ch chan string) {
	for {
		line := <-ch
		fmt.Println("[sub]: " + line)
	}
}

func main() {
	ch := make(chan string)
	http.Handle("/tail", websocket.Handler(makeWebsocketHandlerWithChannel(ch, websocketTailHandler)))
	http.HandleFunc("/", indexHandler)

	if err := startTail(os.Args[1], ch); err != nil {
		panic(err)
	}

	fmt.Println("start wstail...")
	err := http.ListenAndServe(":23456", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
	//pseudoSubscriber(ch)
}
<commit_msg>specify json tag to Data struct<commit_after>package main

import (
	"code.google.com/p/go.net/websocket"
	"fmt"
	"io"
	"net/http"
	"os"
)

func indexHandler(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, `

`)
}

func startTail(file string, ch chan string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	fileInfo, err := f.Stat()
	if err != nil {
		return err
	}
	fileSize := fileInfo.Size()
	var bufSizeMax int64 = 1024
	var bufSize int64
	if fileSize > bufSizeMax {
		bufSize = bufSizeMax
	} else {
		bufSize = fileSize
	}
	go func() {
		fmt.Println("tail start")
		ch <- file
		buf := make([]byte, bufSize)
		var offset int64 = 0
		{
			n, err := f.ReadAt(buf, offset+bufSize)
			if err != nil && err != io.EOF {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			fmt.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		for {
			n, err := f.Read(buf)
			if err == io.EOF && n == 0 {
				continue
			}
			if err != nil {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			fmt.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		fmt.Println("tail end")
	}()
	return nil
}

func makeWebsocketHandlerWithChannel(ch chan string, f func(chan string, *websocket.Conn)) func(*websocket.Conn) {
	return func(ws *websocket.Conn) {
		f(ch, ws)
	}
}

type Data struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func websocketTailHandler(ch chan string, ws *websocket.Conn) {
	fmt.Printf("tailHandler %v\n", ws)
	// send first line as file name
	fileName := <-ch
	if err := websocket.JSON.Send(ws, Data{"filename", fileName}); err != nil {
		fmt.Println("ERR:websoket.Message.Send(): " + err.Error())
	}
	for {
		line := <-ch
		if err := websocket.JSON.Send(ws, Data{"msg", line}); err != nil {
			fmt.Println("ERR:websoket.Message.Send(): " + err.Error())
		}
		fmt.Printf("tailHandler write[%v]\n", line)
	}
	fmt.Println("tailHandler finished")
}

// for debug
func pseudoSubscriber(ch chan string) {
	for {
		line := <-ch
		fmt.Println("[sub]: " + line)
	}
}

func main() {
	ch := make(chan string)
	http.Handle("/tail", websocket.Handler(makeWebsocketHandlerWithChannel(ch, websocketTailHandler)))
	http.HandleFunc("/", indexHandler)

	if err := startTail(os.Args[1], ch); err != nil {
		panic(err)
	}

	fmt.Println("start wstail...")
	err := http.ListenAndServe(":23456", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
	//pseudoSubscriber(ch)
}
<|endoftext|>


<commit_before>package ploop

// A test suite, also serving as an example of how to use the package

import (
	"github.com/dustin/go-humanize"
	"io/ioutil"
	"os"
	"os/exec"
	"testing"
)

var (
	old_pwd  string
	test_dir string
	d        Ploop
	snap     string
)

const baseDelta = "root.hdd"

func TestPrepare(t *testing.T) {
	var err error

	old_pwd, err = os.Getwd()
	if err != nil {
		t.Fatalf("Getwd: %s", err)
	}

	test_dir, err = ioutil.TempDir(old_pwd, "tmp-test")
	if err != nil {
		t.Fatalf("TempDir %q: %s", old_pwd, err)
	}

	err = os.Chdir(test_dir)
	if err != nil {
		t.Fatalf("Chdir %q: %s", test_dir, err)
	}

	SetVerboseLevel(255)
	SetLogLevel(1)
	SetLogFile("ploop.log")

	t.Logf("Running tests in %s", test_dir)
}

func TestUuid(t *testing.T) {
	uuid, e := Uuid()
	if e != nil {
		t.Errorf("Uuid: %s", e)
	}

	t.Logf("Got uuid %s", uuid)
}

func TestCreate(t *testing.T) {
	size := "512M"
	var p CreateParam

	s, e := humanize.ParseBytes(size)
	if e != nil {
		t.Fatalf("humanize.ParseBytes: can't parse %s: %s", size, e)
	}
	p.size = s
	p.file = baseDelta

	e = Create(&p)
	if e != nil {
		t.Fatalf("Create: %s", e)
	}
}

func TestOpen(t *testing.T) {
	var e error

	d, e = Open("DiskDescriptor.xml")
	if e != nil {
		t.Errorf("Open: %s ", e)
	}
}

func TestMount(t *testing.T) {
	mnt := "mnt"

	e := os.Mkdir(mnt, 0755)
	if e != nil {
		t.Fatalf("os.Mkdir: %s", e)
	}

	p := MountParam{target: mnt}
	dev, e := Mount(d, &p)
	if e != nil {
		t.Fatalf("Open: %s", e)
	} else {
		t.Logf("Mounted; ploop device %s", dev)
	}
}

func TestOnlineDownsize(t *testing.T) {
	size := "384M"
	s, e := humanize.ParseBytes(size)
	if e != nil {
		t.Fatalf("humanize.ParseBytes: can't parse %s: %s", size, e)
	}

	e = Resize(d, s, false)
	if e != nil {
		t.Fatalf("Resize to %s (%d) failed: %s", size, s, e)
	}
}

func TestSnapshot(t *testing.T) {
	uuid, e := Snapshot(d)
	if e != nil {
		t.Fatalf("Snapshot: %s", e)
	} else {
		t.Logf("Created online Snapshot; uuid %s", uuid)
	}

	snap = uuid
}

func copyFile(src, dst string) error {

	cmd := exec.Command("cp", "-a", src, dst)
	err := cmd.Run()

	return err
}

func testReplace(t *testing.T) {
	var p ReplaceParam
	newDelta := baseDelta + ".new"
	e := copyFile(baseDelta, newDelta)
	if e != nil {
		t.Fatalf("copyFile: %s", e)
	}

	p.file = newDelta
	p.curFile = baseDelta
	p.flags = keepName
	e = Replace(d, &p)
	if e != nil {
		t.Fatalf("Replace: %s", e)
	}
}

func TestReplaceOnline(t *testing.T) {
	testReplace(t)
}

func TestSnapshotDelete(t *testing.T) {
	e := DeleteSnapshot(d, snap)
	if e != nil {
		t.Fatalf("DeleteSnapshot: %s", e)
	} else {
		t.Logf("Deleted snapshot %s", snap)
	}
}

func TestUmount(t *testing.T) {
	e := Umount(d)
	if e != nil {
		t.Fatalf("Umount: %s", e)
	}
}

func TestSnapshotOffline(t *testing.T) {
	uuid, e := Snapshot(d)
	if e != nil {
		t.Fatalf("Snapshot: %s", e)
	} else {
		t.Logf("Created offline Snapshot; uuid %s", uuid)
	}

	snap = uuid
}

func TestReplaceOffline(t *testing.T) {
	testReplace(t)
}

func TestSnapshotSwitch(t *testing.T) {
	e := SwitchSnapshot(d, snap)
	if e != nil {
		t.Fatalf("SwitchSnapshot: %s", e)
	} else {
		t.Logf("Switched to snapshot %s", snap)
	}
}

func TestFSInfo(t *testing.T) {
	i, e := FSInfo("DiskDescriptor.xml")

	if e != nil {
		t.Errorf("FSInfo: %v", e)
	} else {
		bTotal := i.blocks * i.blocksize
		bAvail := i.blocks_free * i.blocksize
		bUsed := bTotal - bAvail

		iTotal := i.inodes
		iAvail := i.inodes_free
		iUsed := iTotal - iAvail

		t.Logf("\n             Size       Used      Avail Use%%\n%7s %9s %10s %10s %3d%%\n%7s %9d %10d %10d %3d%%",
			"Blocks",
			humanize.Bytes(bTotal),
			humanize.Bytes(bUsed),
			humanize.Bytes(bAvail),
			100*bUsed/bTotal,
			"Inodes",
			iTotal,
			iUsed,
			iAvail,
			100*iUsed/iTotal)
		t.Logf("\nInode ratio: 1 inode per %s of disk space",
			humanize.Bytes(bTotal/iTotal))
	}
}

func TestImageInfo(t *testing.T) {
	i, e := ImageInfo(d)
	if e != nil {
		t.Errorf("ImageInfo: %v", e)
	} else {
		t.Logf("\n              Blocks  Blocksize       Size  Ver\n%20d %10d %10s %4d",
			i.blocks, i.blocksize,
			humanize.Bytes(512*i.blocks),
			i.version)
	}

}

// TestCleanup is the last test, removing files created by previous tests
func TestCleanup(t *testing.T) {
	Close(d)
	os.Chdir(old_pwd)
	os.RemoveAll(test_dir)
}
<commit_msg>test: add variety of tests for Resize()<commit_after>package ploop

// A test suite, also serving as an example of how to use the package

import (
	"github.com/dustin/go-humanize"
	"io/ioutil"
	"os"
	"os/exec"
	"testing"
)

var (
	old_pwd  string
	test_dir string
	d        Ploop
	snap     string
)

const baseDelta = "root.hdd"

func TestPrepare(t *testing.T) {
	var err error

	old_pwd, err = os.Getwd()
	if err != nil {
		t.Fatalf("Getwd: %s", err)
	}

	test_dir, err = ioutil.TempDir(old_pwd, "tmp-test")
	if err != nil {
		t.Fatalf("TempDir %q: %s", old_pwd, err)
	}

	err = os.Chdir(test_dir)
	if err != nil {
		t.Fatalf("Chdir %q: %s", test_dir, err)
	}

	SetVerboseLevel(255)
	SetLogLevel(1)
	SetLogFile("ploop.log")

	t.Logf("Running tests in %s", test_dir)
}

func TestUuid(t *testing.T) {
	uuid, e := Uuid()
	if e != nil {
		t.Errorf("Uuid: %s", e)
	}

	t.Logf("Got uuid %s", uuid)
}

func TestCreate(t *testing.T) {
	size := "384M"
	var p CreateParam

	s, e := humanize.ParseBytes(size)
	if e != nil {
		t.Fatalf("humanize.ParseBytes: can't parse %s: %s", size, e)
	}
	p.size = s
	p.file = baseDelta

	e = Create(&p)
	if e != nil {
		t.Fatalf("Create: %s", e)
	}
}

func TestOpen(t *testing.T) {
	var e error

	d, e = Open("DiskDescriptor.xml")
	if e != nil {
		t.Errorf("Open: %s ", e)
	}
}

func TestMount(t *testing.T) {
	mnt := "mnt"

	e := os.Mkdir(mnt, 0755)
	if e != nil {
		t.Fatalf("os.Mkdir: %s", e)
	}

	p := MountParam{target: mnt}
	dev, e := Mount(d, &p)
	if e != nil {
		t.Fatalf("Open: %s", e)
	} else {
		t.Logf("Mounted; ploop device %s", dev)
	}
}

func resize(t *testing.T, size string, offline bool) {
	if offline && testing.Short() {
		t.Skip("skipping offline resize test in short mode.")
	}
	s, e := humanize.ParseBytes(size)
	if e != nil {
		t.Fatalf("humanize.ParseBytes: can't parse %s: %s", size, e)
	}

	e = Resize(d, s, offline)
	if e != nil {
		t.Fatalf("Resize to %s (%d) failed: %s", size, s, e)
	}
}

func TestResizeOnlineShrink(t *testing.T) {
	resize(t, "256MB", false)
}

func TestResizeOnlineGrow(t *testing.T) {
	resize(t, "512MB", false)
}

func TestSnapshot(t *testing.T) {
	uuid, e := Snapshot(d)
	if e != nil {
		t.Fatalf("Snapshot: %s", e)
	} else {
		t.Logf("Created online Snapshot; uuid %s", uuid)
	}

	snap = uuid
}

func copyFile(src, dst string) error {

	cmd := exec.Command("cp", "-a", src, dst)
	err := cmd.Run()

	return err
}

func testReplace(t *testing.T) {
	var p ReplaceParam
	newDelta := baseDelta + ".new"
	e := copyFile(baseDelta, newDelta)
	if e != nil {
		t.Fatalf("copyFile: %s", e)
	}

	p.file = newDelta
	p.curFile = baseDelta
	p.flags = keepName
	e = Replace(d, &p)
	if e != nil {
		t.Fatalf("Replace: %s", e)
	}
}

func TestReplaceOnline(t *testing.T) {
	testReplace(t)
}

func TestSnapshotDelete(t *testing.T) {
	e := DeleteSnapshot(d, snap)
	if e != nil {
		t.Fatalf("DeleteSnapshot: %s", e)
	} else {
		t.Logf("Deleted snapshot %s", snap)
	}
}

func TestUmount(t *testing.T) {
	e := Umount(d)
	if e != nil {
		t.Fatalf("Umount: %s", e)
	}
}

func TestResizeOfflineShrink(t *testing.T) {
	resize(t, "256MB", true)
}

func TestResizeOfflineGrow(t *testing.T) {
	resize(t, "512MB", true)
}

func TestResizeOfflineShrinkAgain(t *testing.T) {
	resize(t, "256MB", true)
}

func TestSnapshotOffline(t *testing.T) {
	uuid, e := Snapshot(d)
	if e != nil {
		t.Fatalf("Snapshot: %s", e)
	} else {
		t.Logf("Created offline Snapshot; uuid %s", uuid)
	}

	snap = uuid
}

func TestReplaceOffline(t *testing.T) {
	testReplace(t)
}

func TestSnapshotSwitch(t *testing.T) {
	e := SwitchSnapshot(d, snap)
	if e != nil {
		t.Fatalf("SwitchSnapshot: %s", e)
	} else {
		t.Logf("Switched to snapshot %s", snap)
	}
}

func TestFSInfo(t *testing.T) {
	i, e := FSInfo("DiskDescriptor.xml")

	if e != nil {
		t.Errorf("FSInfo: %v", e)
	} else {
		bTotal := i.blocks * i.blocksize
		bAvail := i.blocks_free * i.blocksize
		bUsed := bTotal - bAvail

		iTotal := i.inodes
		iAvail := i.inodes_free
		iUsed := iTotal - iAvail

		t.Logf("\n             Size       Used      Avail Use%%\n%7s %9s %10s %10s %3d%%\n%7s %9d %10d %10d %3d%%",
			"Blocks",
			humanize.Bytes(bTotal),
			humanize.Bytes(bUsed),
			humanize.Bytes(bAvail),
			100*bUsed/bTotal,
			"Inodes",
			iTotal,
			iUsed,
			iAvail,
			100*iUsed/iTotal)
		t.Logf("\nInode ratio: 1 inode per %s of disk space",
			humanize.Bytes(bTotal/iTotal))
	}
}

func TestImageInfo(t *testing.T) {
	i, e := ImageInfo(d)
	if e != nil {
		t.Errorf("ImageInfo: %v", e)
	} else {
		t.Logf("\n              Blocks  Blocksize       Size  Ver\n%20d %10d %10s %4d",
			i.blocks, i.blocksize,
			humanize.Bytes(512*i.blocks),
			i.version)
	}

}

// TestCleanup is the last test, removing files created by previous tests
func TestCleanup(t *testing.T) {
	Close(d)
	os.Chdir(old_pwd)
	os.RemoveAll(test_dir)
}
<|endoftext|>


<commit_before>package plugin

import (
	"regexp"
	"strings"

	"github.com/j6n/noye/noye"
)

type Command struct {
	Respond bool
	Command string
	Each    bool
	Strict  bool
	Matcher func(string) (bool, string)

	results []string
}

func (c *Command) Match(msg noye.Message) bool {
	// split text in parts so we can drop nick/cmd if needed
	parts := strings.Fields(msg.Text)

	// check to see if a nick was prefixed
	if c.Respond {
		nick := "noye" // TODO get current nick
		ok, err := regexp.MatchString(`(?:`+nick+`[:,]?\s*)`, parts[0])
		if err != nil || !ok {
			return false
		}
	}

	// less typing for later
	hasCommand := c.Command != ""

	// if we expect a nick prefix and a command, but only have 1 part
	if (len(parts) == 1 && c.Respond) && hasCommand {
		return false
	}

	index := 0
	// skip first element if we've matched against `respond`
	if c.Respond {
		index++
	}

	// if we have a command, check to see if it matches the next part
	if hasCommand && !strings.EqualFold(c.Command, parts[index]) {
		return false
	}

	// skip next element if we've matched against `respond`
	if c.Respond || hasCommand {
		index++
	}

	// if no default matcher was provided, give them one that always returns true
	if c.Matcher == nil {
		c.Matcher = func(string) (bool, string) { return true, "" }
	}

	// if we're using the matcher against each part
	if c.Each {
		success := true
		// ...then match each remaining part
		for _, part := range parts[index:] {
			if ok, s := c.Matcher(part); ok {
				if s != "" {
					c.results = append(c.results, s)
				}
			} else if c.Strict {
				success = false
			}
		}

		// nothing else to do, we've succeeded
		return success
	}

	// match against the parts rejoined as a string
	ok, s := c.Matcher(strings.Join(parts[index:], " "))
	if ok && s != "" {
		c.results = append(c.results, s)
	}

	return ok
}

func (c *Command) Results() []string {
	return c.results
}
<commit_msg>reset results on each command match<commit_after>package plugin

import (
	"regexp"
	"strings"

	"github.com/j6n/noye/noye"
)

type Command struct {
	Respond bool
	Command string
	Each    bool
	Strict  bool
	Matcher func(string) (bool, string)

	results []string
}

func (c *Command) Match(msg noye.Message) bool {
	// reset the results
	c.results = make([]string, 0)

	// split text in parts so we can drop nick/cmd if needed
	parts := strings.Fields(msg.Text)

	// check to see if a nick was prefixed
	if c.Respond {
		nick := "noye" // TODO get current nick
		ok, err := regexp.MatchString(`(?:`+nick+`[:,]?\s*)`, parts[0])
		if err != nil || !ok {
			return false
		}
	}

	// less typing for later
	hasCommand := c.Command != ""

	// if we expect a nick prefix and a command, but only have 1 part
	if (len(parts) == 1 && c.Respond) && hasCommand {
		return false
	}

	index := 0
	// skip first element if we've matched against `respond`
	if c.Respond {
		index++
	}

	// if we have a command, check to see if it matches the next part
	if hasCommand && !strings.EqualFold(c.Command, parts[index]) {
		return false
	}

	// skip next element if we've matched against `respond`
	if c.Respond || hasCommand {
		index++
	}

	// if no default matcher was provided, give them one that always returns true
	if c.Matcher == nil {
		c.Matcher = func(string) (bool, string) { return true, "" }
	}

	// if we're using the matcher against each part
	if c.Each {
		success := true
		// ...then match each remaining part
		for _, part := range parts[index:] {
			if ok, s := c.Matcher(part); ok {
				if s != "" {
					c.results = append(c.results, s)
				}
			} else if c.Strict {
				success = false
			}
		}

		// nothing else to do, we've succeeded
		return success
	}

	// match against the parts rejoined as a string
	ok, s := c.Matcher(strings.Join(parts[index:], " "))
	if ok && s != "" {
		c.results = append(c.results, s)
	}

	return ok
}

func (c *Command) Results() []string {
	return c.results
}
<|endoftext|>


<commit_before>package server
import (
	"servant/conf"
	"time"
	"os/exec"
	"sync"
	"syscall"
	"os/signal"
	"os"
)

var taskProcesses = make(map[int] *exec.Cmd)
var taskProcessesLock sync.Mutex
var _isExiting bool = false

func registerProcess(cmd *exec.Cmd) {
	taskProcessesLock.Lock()
	taskProcesses[cmd.Process.Pid] = cmd
	taskProcessesLock.Unlock()
}

func unregisterProcess(cmd *exec.Cmd) {
	taskProcessesLock.Lock()
	delete(taskProcesses, cmd.Process.Pid)
	taskProcessesLock.Unlock()
}

func isExiting() bool {
	taskProcessesLock.Lock()
	ret := _isExiting
	taskProcessesLock.Unlock()
	return ret
}

func RunTimer(name string, timerConf *conf.Timer) {
	if timerConf.Tick <= 0 {
		logger.Printf("WARN (_) [timer] %s tick not set", name)
		return
	}
	cmdConf := conf.Command {
		Lang: timerConf.Lang,
		Code: timerConf.Code,
		User: timerConf.User,
		Background: true,
		Timeout: timerConf.Deadline,
	}
	ticker := time.NewTicker(time.Duration(timerConf.Tick) * time.Second)
	logger.Printf("INFO (_) [timer] starting timer %s", name)
	for _ = range(ticker.C) {
		if isExiting() {
			break
		}
		cmd, out, err := cmdFromConf(&cmdConf, nil, nil)
		if err != nil {
			logger.Printf("WARN (_) [timer] create %s command failed: %s", name, err.Error())
			break
		}
		if out != nil {
			out.Close()
		}
		err = cmd.Start()
		if err != nil {
			logger.Printf("WARN (_) [timer] start %s command failed: %s", name, err.Error())
			break
		}
		//registerProcess(cmd)
		ch := make(chan error, 1)
		go func() {
			err = cmd.Wait()
			ch <- err
		}()
		timeout := time.Duration(cmdConf.Timeout)
		select {
		case err = <-ch:
			if err != nil {
				logger.Printf("WARN (_) [timer] %s command execution failed: %s", name, err.Error())
			}
		case <-time.After(timeout * time.Second):
			cmd.Process.Kill()
			logger.Printf("WARN (_) [timer] %s command execution timeout: %d", name, timeout)
		}
		//unregisterProcess(cmd)
	}
	ticker = nil
}

func RunDaemon(name string, daemonConf *conf.Daemon) {
	cmdConf := conf.Command {
		Lang: daemonConf.Lang,
		Code: daemonConf.Code,
		User: daemonConf.User,
		Background: true,
	}
	if daemonConf.Retries < 0 {
		daemonConf.Retries = 0
	}
	logger.Printf("INFO (_) [daemon] starting daemon %s", name)
	cleanupOnExit()
	for i := 0; i < daemonConf.Retries + 1; i++ {
		if isExiting() {
			return
		}
		cmd, out, err := cmdFromConf(&cmdConf, nil, nil)
		if out != nil {
			out.Close()
		}
		if err != nil {
			logger.Printf("WARN (_) [daemon] create %s command failed: %s", name, err.Error())
			return
		}
		err = cmd.Start()
		if err != nil {
			logger.Printf("WARN (_) [daemon] start %s failed: %s", name, err.Error())
			return
		}
		logger.Printf("INFO (_) [daemon] %s started. pid: %d", name, cmd.Process.Pid)
		t0 := time.Now()
		registerProcess(cmd)
		err = cmd.Wait()
		unregisterProcess(cmd)
		if err == nil {
			logger.Printf("WARN (_) [daemon] %s normal exit", name)
			return
		}
		t1 := time.Now()
		if t1.Sub(t0) >= time.Duration(daemonConf.Live) * time.Second {
			i = 0
		}
	}
	logger.Printf("WARN (_) [daemon] %s give up after %d retries", name, daemonConf.Retries)
}

func cleanupOnExit() {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		sig := <- sigChan
		logger.Printf("INFO (_) [daemon] got signal %s", sig.String())
		cleanupProcesses()
		logger.Printf("INFO (_) [daemon] cleaning up done")
		os.Exit(0)
	}()
}

func cleanupProcesses() {
	logger.Printf("INFO (_) [daemon] cleaning up process")
	taskProcessesLock.Lock()
	_isExiting = true
	taskProcessesLock.Unlock()

	for i := 0; i < 10; i++ { // in about 100ms
		taskProcessesLock.Lock()
		for _, cmd := range(taskProcesses) {
			if cmd.Process.Signal(syscall.SIGTERM) != nil {
				delete(taskProcesses, cmd.Process.Pid)
				logger.Printf("INFO (_) [daemon] process %d terminated", cmd.Process.Pid)
			}
		}
		taskProcessesLock.Unlock()
		time.Sleep(10 * time.Millisecond)
	}
	for _, cmd := range(taskProcesses) {
		logger.Printf("INFO (_) [daemon] killing process %d ", cmd.Process.Pid)
		cmd.Process.Kill()
	}
	taskProcessesLock.Lock()
	taskProcesses = map[int]*exec.Cmd{}
	taskProcessesLock.Unlock()
}
<commit_msg>tasks use params<commit_after>package server
import (
	"servant/conf"
	"time"
	"os/exec"
	"sync"
	"syscall"
	"os/signal"
	"os"
)

var taskProcesses = make(map[int] *exec.Cmd)
var taskProcessesLock sync.Mutex
var _isExiting bool = false

func registerProcess(cmd *exec.Cmd) {
	taskProcessesLock.Lock()
	taskProcesses[cmd.Process.Pid] = cmd
	taskProcessesLock.Unlock()
}

func unregisterProcess(cmd *exec.Cmd) {
	taskProcessesLock.Lock()
	delete(taskProcesses, cmd.Process.Pid)
	taskProcessesLock.Unlock()
}

func isExiting() bool {
	taskProcessesLock.Lock()
	ret := _isExiting
	taskProcessesLock.Unlock()
	return ret
}

func RunTimer(name string, timerConf *conf.Timer) {
	if timerConf.Tick <= 0 {
		logger.Printf("WARN (_) [timer] %s tick not set", name)
		return
	}
	cmdConf := conf.Command {
		Lang: timerConf.Lang,
		Code: timerConf.Code,
		User: timerConf.User,
		Background: true,
		Timeout: timerConf.Deadline,
	}
	ticker := time.NewTicker(time.Duration(timerConf.Tick) * time.Second)
	logger.Printf("INFO (_) [timer] starting timer %s", name)
	for _ = range(ticker.C) {
		if isExiting() {
			break
		}
		cmd, out, err := cmdFromConf(&cmdConf, requestParams(nil), nil)
		if err != nil {
			logger.Printf("WARN (_) [timer] create %s command failed: %s", name, err.Error())
			break
		}
		if out != nil {
			out.Close()
		}
		err = cmd.Start()
		if err != nil {
			logger.Printf("WARN (_) [timer] start %s command failed: %s", name, err.Error())
			break
		}
		//registerProcess(cmd)
		ch := make(chan error, 1)
		go func() {
			err = cmd.Wait()
			ch <- err
		}()
		timeout := time.Duration(cmdConf.Timeout)
		select {
		case err = <-ch:
			if err != nil {
				logger.Printf("WARN (_) [timer] %s command execution failed: %s", name, err.Error())
			}
		case <-time.After(timeout * time.Second):
			cmd.Process.Kill()
			logger.Printf("WARN (_) [timer] %s command execution timeout: %d", name, timeout)
		}
		//unregisterProcess(cmd)
	}
	ticker = nil
}

func RunDaemon(name string, daemonConf *conf.Daemon) {
	cmdConf := conf.Command {
		Lang: daemonConf.Lang,
		Code: daemonConf.Code,
		User: daemonConf.User,
		Background: true,
	}
	if daemonConf.Retries < 0 {
		daemonConf.Retries = 0
	}
	logger.Printf("INFO (_) [daemon] starting daemon %s", name)
	cleanupOnExit()
	for i := 0; i < daemonConf.Retries + 1; i++ {
		if isExiting() {
			return
		}
		cmd, out, err := cmdFromConf(&cmdConf, requestParams(nil), nil)
		if out != nil {
			out.Close()
		}
		if err != nil {
			logger.Printf("WARN (_) [daemon] create %s command failed: %s", name, err.Error())
			return
		}
		err = cmd.Start()
		if err != nil {
			logger.Printf("WARN (_) [daemon] start %s failed: %s", name, err.Error())
			return
		}
		logger.Printf("INFO (_) [daemon] %s started. pid: %d", name, cmd.Process.Pid)
		t0 := time.Now()
		registerProcess(cmd)
		err = cmd.Wait()
		unregisterProcess(cmd)
		if err == nil {
			logger.Printf("WARN (_) [daemon] %s normal exit", name)
			return
		}
		t1 := time.Now()
		if t1.Sub(t0) >= time.Duration(daemonConf.Live) * time.Second {
			i = 0
		}
	}
	logger.Printf("WARN (_) [daemon] %s give up after %d retries", name, daemonConf.Retries)
}

func cleanupOnExit() {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		sig := <- sigChan
		logger.Printf("INFO (_) [daemon] got signal %s", sig.String())
		cleanupProcesses()
		logger.Printf("INFO (_) [daemon] cleaning up done")
		os.Exit(0)
	}()
}

func cleanupProcesses() {
	logger.Printf("INFO (_) [daemon] cleaning up process")
	taskProcessesLock.Lock()
	_isExiting = true
	taskProcessesLock.Unlock()

	for i := 0; i < 10; i++ { // in about 100ms
		taskProcessesLock.Lock()
		for _, cmd := range(taskProcesses) {
			if cmd.Process.Signal(syscall.SIGTERM) != nil {
				delete(taskProcesses, cmd.Process.Pid)
				logger.Printf("INFO (_) [daemon] process %d terminated", cmd.Process.Pid)
			}
		}
		taskProcessesLock.Unlock()
		time.Sleep(10 * time.Millisecond)
	}
	for _, cmd := range(taskProcesses) {
		logger.Printf("INFO (_) [daemon] killing process %d ", cmd.Process.Pid)
		cmd.Process.Kill()
	}
	taskProcessesLock.Lock()
	taskProcesses = map[int]*exec.Cmd{}
	taskProcessesLock.Unlock()
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2010 Andrea Fazzi

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

/*

PrettyTest is a simple assertion testing library for golang. It aims
to simplify/prettify testing in golang.

It features:

* a simple assertion vocabulary for better readability
* colorful output

*/

package prettytest

import (
	"testing"
	"runtime"
	"reflect"
	"regexp"
	"strings"
	"os"
	"fmt"
)

const (
	STATUS_PASS = iota
	STATUS_FAIL
	STATUS_PENDING
)

const formatTag = "\t%s\t"

func green(text string) string {
	return fmt.Sprintf("\033[32m%s\033[0m", text)
}

func red(text string) string {
	return fmt.Sprintf("\033[31m%s\033[0m", text)
}

func yellow(text string) string {
	return fmt.Sprintf("\033[33m%s\033[0m", text)
}

var (
	labelFAIL    = red("FAIL")
	labelPASS    = green("OK")
	labelPENDING = yellow("PENDING")
)

type callerInfo struct {
	name, fn string
	line     int
}

func newCallerInfo(skip int) *callerInfo {
	pc, fn, line, ok := runtime.Caller(skip)
	if !ok {
		panic("An error occured while retrieving caller info!")
	}
	callerName := strings.Split(runtime.FuncForPC(pc).Name(), ".", -1)[1]
	return &callerInfo{callerName, fn, line}
}

type TCatcher interface {
	SetT(t *testing.T)
	GetLastStatus() byte
	GetStatus() byte
	SetStatus(status byte)
	GetInfo() *suiteInfo
	Reset()
}

type suiteInfo struct {
	assertions int
	callerName string
}

type Suite struct {
	T                  *testing.T
	Status, LastStatus byte
	callerInfo         *callerInfo
	info               map[string]*suiteInfo
}

// Formatters
type Formatter interface {
	PrintSuiteName(name string)
	PrintStatus(status byte, info *suiteInfo)
	PrintFinalReport(passed, failed, pending int)
	AllowedMethodsPattern() string
}

type TDDFormatter struct{}

func (formatter *TDDFormatter) PrintSuiteName(name string) {
	fmt.Printf("\n%s:\n", name)
}

func (formatter *TDDFormatter) PrintStatus(status byte, info *suiteInfo) {
	switch status {
	case STATUS_FAIL:
		fmt.Printf(formatTag+"%-30s(%d assertion(s))\n", labelFAIL, strings.Split(info.callerName, "·", -1)[1], info.assertions)
	case STATUS_PASS:
		fmt.Printf(formatTag+"%-30s(%d assertion(s))\n", labelPASS, strings.Split(info.callerName, "·", -1)[1], info.assertions)
	case STATUS_PENDING:
		fmt.Printf(formatTag+"%s\n", labelPENDING, strings.Split(info.callerName, "·", -1)[1])

	}
}

func (formatter *TDDFormatter) PrintFinalReport(passed, failed, pending int) {
	total := passed + failed + pending
	fmt.Printf("\n%d tests, %d passed, %d failed, %d pending\n", total, passed, failed, pending)
}

func (formatter *TDDFormatter) AllowedMethodsPattern() string {
	return "^Test.*"
}

type BDDFormatter struct {
	Description string
}

func (formatter *BDDFormatter) PrintSuiteName(name string) {
	fmt.Printf("\n%s:\n", formatter.Description)
}

func (formatter *BDDFormatter) PrintStatus(status byte, info *suiteInfo) {
	shouldText := formatter.splitString(info.callerName, "·")

	switch status {
	case STATUS_FAIL:
		fmt.Printf("- %s\n", red(shouldText))
	case STATUS_PASS:
		fmt.Printf("- %s\n", green(shouldText))
	case STATUS_PENDING:
		fmt.Printf("- %s\t(Not Yet Implemented)\n", yellow(shouldText))
	}
}

func (formatter *BDDFormatter) PrintFinalReport(passed, failed, pending int) {
	total := passed + failed + pending
	fmt.Printf("\n%d examples, %d passed, %d failed, %d pending\n", total, passed, failed, pending)
}

func (formatter *BDDFormatter) AllowedMethodsPattern() string {
	return "^Should_.*"
}

func (formatter *BDDFormatter) splitString(text, sep string) (result string) {
	s := strings.Split(text, sep, -1)

	if len(s) < 2 {
		panic("Can't use BDD formatter!")
	}

	stringWithUnderscores := s[1]
	splittedByUnderscores := strings.Split(stringWithUnderscores, "_", -1)

	for _, v := range splittedByUnderscores {
		result += v + " "
	}
	return strings.TrimSpace(result)
}

func (s *Suite) SetT(t *testing.T)          { s.T = t }
func (s *Suite) GetLastStatus() byte        { return s.LastStatus }
func (s *Suite) GetStatus() byte            { return s.Status }
func (s *Suite) SetStatus(status byte)      { s.Status = status }
func (s *Suite) GetCallerInfo() *callerInfo { return s.callerInfo }
func (s *Suite) GetInfo() *suiteInfo        { return s.info[s.callerInfo.name] }

func (s *Suite) Reset() {
	s.info = make(map[string]*suiteInfo)
}

func (s *Suite) fail(exp, act interface{}, info *callerInfo) {
	s.T.Errorf("Expected %s but got %s -- %s:%d\n", exp, act, info.fn, info.line)
	s.Status, s.LastStatus = STATUS_FAIL, STATUS_FAIL
}

func (s *Suite) failWithCustomMsg(msg string, info *callerInfo) {
	s.T.Errorf("%s -- %s:%d\n", msg, info.fn, info.line)
	s.Status, s.LastStatus = STATUS_FAIL, STATUS_FAIL
}

func (s *Suite) setup() {
	s.LastStatus = STATUS_PASS
	s.callerInfo = newCallerInfo(3)
	if _, present := s.info[s.callerInfo.name]; !present {
		s.info[s.callerInfo.name] = new(suiteInfo)

	}
	s.info[s.callerInfo.name].callerName = s.callerInfo.name
	s.info[s.callerInfo.name].assertions++
}

// Assert that the expected value equals the actual value.
func (s *Suite) Equal(exp, act interface{}) {
	s.setup()
	if exp != act {
		s.fail(exp, act, s.callerInfo)
	}
}

// Assert that the expected value is not equal to the actual
// value.
func (s *Suite) NotEqual(exp, act interface{}) {
	s.setup()
	if exp == act {
		s.fail(exp, act, s.callerInfo)
	}
}

// Assert that the value is true.
func (s *Suite) True(value bool) {
	s.setup()
	if !value {
		s.fail("true", "false", s.callerInfo)
	}
}

// Assert that the value is false.
func (s *Suite) False(value bool) {
	s.setup()
	if value {
		s.fail("false", "true", s.callerInfo)
	}
}

// Assert that the given path exists.
func (s *Suite) Path(path string) {
	s.setup()
	if _, err := os.Stat(path); err != nil {
		s.failWithCustomMsg(fmt.Sprintf("Path %s doesn't exist", path), s.callerInfo)
	}
}

// Assert that the value is nil.
func (s *Suite) Nil(value interface{}) {
	s.setup()
	if value != nil {
		s.failWithCustomMsg(fmt.Sprintf("Expected nil but got %s", value), s.callerInfo)
	}
}

// Assert that the value is not nil.
func (s *Suite) NotNil(value interface{}) {
	s.setup()
	if value == nil {
		s.failWithCustomMsg(fmt.Sprintf("Expected not nil value but got %s", value), s.callerInfo)
	}
}

// Mark the test function as pending.
func (s *Suite) Pending() {
	s.setup()
	s.Status = STATUS_PENDING
}

// Check if the last assertion has failed.
func (s *Suite) Failed() bool {
	return s.LastStatus == STATUS_FAIL
}

// Check if the test function has failed.
func (s *Suite) FailedTest() bool {
	return s.Status == STATUS_FAIL
}

func Run(t *testing.T, suites ...TCatcher) {
	run(t, new(TDDFormatter), suites...)
}

func RunWithFormatter(t *testing.T, formatter Formatter, suites ...TCatcher) {
	run(t, formatter, suites...)
}

// Run tests. Use default formatter.
func run(t *testing.T, formatter Formatter, suites ...TCatcher) {
	var (
		beforeAllFound, afterAllFound          bool
		beforeAll, afterAll, before, after     reflect.Value
		totalPassed, totalFailed, totalPending int
	)

	for _, s := range suites {
		beforeAll, afterAll, before, after = reflect.Value{}, reflect.Value{}, reflect.Value{}, reflect.Value{}
		s.SetT(t)
		s.Reset()

		iType := reflect.TypeOf(s)

		formatter.PrintSuiteName(iType.String())

		// search for Before and After methods
		for i := 0; i < iType.NumMethod(); i++ {
			method := iType.Method(i)
			if ok, _ := regexp.MatchString("^BeforeAll", method.Name); ok {
				if !beforeAllFound {
					beforeAll = method.Func
					beforeAllFound = true
					continue
				}
			}
			if ok, _ := regexp.MatchString("^AfterAll", method.Name); ok {
				if !afterAllFound {
					afterAll = method.Func
					afterAllFound = true
					continue
				}
			}
			if ok, _ := regexp.MatchString("^Before", method.Name); ok {
				before = method.Func
			}
			if ok, _ := regexp.MatchString("^After", method.Name); ok {
				after = method.Func
			}
		}

		if beforeAll.IsValid() {
			beforeAll.Call([]reflect.Value{reflect.ValueOf(s)})
		}

		for i := 0; i < iType.NumMethod(); i++ {
			method := iType.Method(i)

			if ok, _ := regexp.MatchString(formatter.AllowedMethodsPattern(), method.Name); ok {

				s.SetStatus(STATUS_PASS)

				if before.IsValid() {
					before.Call([]reflect.Value{reflect.ValueOf(s)})
				}

				method.Func.Call([]reflect.Value{reflect.ValueOf(s)})

				if after.IsValid() {
					after.Call([]reflect.Value{reflect.ValueOf(s)})
				}

				switch s.GetStatus() {
				case STATUS_PASS:
					totalPassed++
				case STATUS_FAIL:
					totalFailed++
				case STATUS_PENDING:
					totalPending++
				}

				formatter.PrintStatus(s.GetStatus(), s.GetInfo())

			}

		}

		if afterAll.IsValid() {
			afterAll.Call([]reflect.Value{reflect.ValueOf(s)})
		}
	}

	formatter.PrintFinalReport(totalPassed, totalFailed, totalPending)
}
<commit_msg>Update in response of golang release.r58<commit_after>/*

Copyright (c) 2010 Andrea Fazzi

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

/*

PrettyTest is a simple assertion testing library for golang. It aims
to simplify/prettify testing in golang.

It features:

* a simple assertion vocabulary for better readability
* colorful output

*/

package prettytest

import (
	"testing"
	"runtime"
	"reflect"
	"regexp"
	"strings"
	"os"
	"fmt"
)

const (
	STATUS_PASS = iota
	STATUS_FAIL
	STATUS_PENDING
)

const formatTag = "\t%s\t"

func green(text string) string {
	return fmt.Sprintf("\033[32m%s\033[0m", text)
}

func red(text string) string {
	return fmt.Sprintf("\033[31m%s\033[0m", text)
}

func yellow(text string) string {
	return fmt.Sprintf("\033[33m%s\033[0m", text)
}

var (
	labelFAIL    = red("FAIL")
	labelPASS    = green("OK")
	labelPENDING = yellow("PENDING")
)

type callerInfo struct {
	name, fn string
	line     int
}

func newCallerInfo(skip int) *callerInfo {
	pc, fn, line, ok := runtime.Caller(skip)
	if !ok {
		panic("An error occured while retrieving caller info!")
	}
	callerName := strings.Split(runtime.FuncForPC(pc).Name(), ".")[1]
	return &callerInfo{callerName, fn, line}
}

type TCatcher interface {
	SetT(t *testing.T)
	GetLastStatus() byte
	GetStatus() byte
	SetStatus(status byte)
	GetInfo() *suiteInfo
	Reset()
}

type suiteInfo struct {
	assertions int
	callerName string
}

type Suite struct {
	T                  *testing.T
	Status, LastStatus byte
	callerInfo         *callerInfo
	info               map[string]*suiteInfo
}

// Formatters
type Formatter interface {
	PrintSuiteName(name string)
	PrintStatus(status byte, info *suiteInfo)
	PrintFinalReport(passed, failed, pending int)
	AllowedMethodsPattern() string
}

type TDDFormatter struct{}

func (formatter *TDDFormatter) PrintSuiteName(name string) {
	fmt.Printf("\n%s:\n", name)
}

func (formatter *TDDFormatter) PrintStatus(status byte, info *suiteInfo) {
	switch status {
	case STATUS_FAIL:
		fmt.Printf(formatTag+"%-30s(%d assertion(s))\n", labelFAIL, strings.Split(info.callerName, "·")[1], info.assertions)
	case STATUS_PASS:
		fmt.Printf(formatTag+"%-30s(%d assertion(s))\n", labelPASS, strings.Split(info.callerName, "·")[1], info.assertions)
	case STATUS_PENDING:
		fmt.Printf(formatTag+"%s\n", labelPENDING, strings.Split(info.callerName, "·")[1])

	}
}

func (formatter *TDDFormatter) PrintFinalReport(passed, failed, pending int) {
	total := passed + failed + pending
	fmt.Printf("\n%d tests, %d passed, %d failed, %d pending\n", total, passed, failed, pending)
}

func (formatter *TDDFormatter) AllowedMethodsPattern() string {
	return "^Test.*"
}

type BDDFormatter struct {
	Description string
}

func (formatter *BDDFormatter) PrintSuiteName(name string) {
	fmt.Printf("\n%s:\n", formatter.Description)
}

func (formatter *BDDFormatter) PrintStatus(status byte, info *suiteInfo) {
	shouldText := formatter.splitString(info.callerName, "·")

	switch status {
	case STATUS_FAIL:
		fmt.Printf("- %s\n", red(shouldText))
	case STATUS_PASS:
		fmt.Printf("- %s\n", green(shouldText))
	case STATUS_PENDING:
		fmt.Printf("- %s\t(Not Yet Implemented)\n", yellow(shouldText))
	}
}

func (formatter *BDDFormatter) PrintFinalReport(passed, failed, pending int) {
	total := passed + failed + pending
	fmt.Printf("\n%d examples, %d passed, %d failed, %d pending\n", total, passed, failed, pending)
}

func (formatter *BDDFormatter) AllowedMethodsPattern() string {
	return "^Should_.*"
}

func (formatter *BDDFormatter) splitString(text, sep string) (result string) {
	s := strings.Split(text, sep)

	if len(s) < 2 {
		panic("Can't use BDD formatter!")
	}

	stringWithUnderscores := s[1]
	splittedByUnderscores := strings.Split(stringWithUnderscores, "_")

	for _, v := range splittedByUnderscores {
		result += v + " "
	}
	return strings.TrimSpace(result)
}

func (s *Suite) SetT(t *testing.T)          { s.T = t }
func (s *Suite) GetLastStatus() byte        { return s.LastStatus }
func (s *Suite) GetStatus() byte            { return s.Status }
func (s *Suite) SetStatus(status byte)      { s.Status = status }
func (s *Suite) GetCallerInfo() *callerInfo { return s.callerInfo }
func (s *Suite) GetInfo() *suiteInfo        { return s.info[s.callerInfo.name] }

func (s *Suite) Reset() {
	s.info = make(map[string]*suiteInfo)
}

func (s *Suite) fail(exp, act interface{}, info *callerInfo) {
	s.T.Errorf("Expected %s but got %s -- %s:%d\n", exp, act, info.fn, info.line)
	s.Status, s.LastStatus = STATUS_FAIL, STATUS_FAIL
}

func (s *Suite) failWithCustomMsg(msg string, info *callerInfo) {
	s.T.Errorf("%s -- %s:%d\n", msg, info.fn, info.line)
	s.Status, s.LastStatus = STATUS_FAIL, STATUS_FAIL
}

func (s *Suite) setup() {
	s.LastStatus = STATUS_PASS
	s.callerInfo = newCallerInfo(3)
	if _, present := s.info[s.callerInfo.name]; !present {
		s.info[s.callerInfo.name] = new(suiteInfo)

	}
	s.info[s.callerInfo.name].callerName = s.callerInfo.name
	s.info[s.callerInfo.name].assertions++
}

// Assert that the expected value equals the actual value.
func (s *Suite) Equal(exp, act interface{}) {
	s.setup()
	if exp != act {
		s.fail(exp, act, s.callerInfo)
	}
}

// Assert that the expected value is not equal to the actual
// value.
func (s *Suite) NotEqual(exp, act interface{}) {
	s.setup()
	if exp == act {
		s.fail(exp, act, s.callerInfo)
	}
}

// Assert that the value is true.
func (s *Suite) True(value bool) {
	s.setup()
	if !value {
		s.fail("true", "false", s.callerInfo)
	}
}

// Assert that the value is false.
func (s *Suite) False(value bool) {
	s.setup()
	if value {
		s.fail("false", "true", s.callerInfo)
	}
}

// Assert that the given path exists.
func (s *Suite) Path(path string) {
	s.setup()
	if _, err := os.Stat(path); err != nil {
		s.failWithCustomMsg(fmt.Sprintf("Path %s doesn't exist", path), s.callerInfo)
	}
}

// Assert that the value is nil.
func (s *Suite) Nil(value interface{}) {
	s.setup()
	if value != nil {
		s.failWithCustomMsg(fmt.Sprintf("Expected nil but got %s", value), s.callerInfo)
	}
}

// Assert that the value is not nil.
func (s *Suite) NotNil(value interface{}) {
	s.setup()
	if value == nil {
		s.failWithCustomMsg(fmt.Sprintf("Expected not nil value but got %s", value), s.callerInfo)
	}
}

// Mark the test function as pending.
func (s *Suite) Pending() {
	s.setup()
	s.Status = STATUS_PENDING
}

// Check if the last assertion has failed.
func (s *Suite) Failed() bool {
	return s.LastStatus == STATUS_FAIL
}

// Check if the test function has failed.
func (s *Suite) FailedTest() bool {
	return s.Status == STATUS_FAIL
}

func Run(t *testing.T, suites ...TCatcher) {
	run(t, new(TDDFormatter), suites...)
}

func RunWithFormatter(t *testing.T, formatter Formatter, suites ...TCatcher) {
	run(t, formatter, suites...)
}

// Run tests. Use default formatter.
func run(t *testing.T, formatter Formatter, suites ...TCatcher) {
	var (
		beforeAllFound, afterAllFound          bool
		beforeAll, afterAll, before, after     reflect.Value
		totalPassed, totalFailed, totalPending int
	)

	for _, s := range suites {
		beforeAll, afterAll, before, after = reflect.Value{}, reflect.Value{}, reflect.Value{}, reflect.Value{}
		s.SetT(t)
		s.Reset()

		iType := reflect.TypeOf(s)

		formatter.PrintSuiteName(iType.String())

		// search for Before and After methods
		for i := 0; i < iType.NumMethod(); i++ {
			method := iType.Method(i)
			if ok, _ := regexp.MatchString("^BeforeAll", method.Name); ok {
				if !beforeAllFound {
					beforeAll = method.Func
					beforeAllFound = true
					continue
				}
			}
			if ok, _ := regexp.MatchString("^AfterAll", method.Name); ok {
				if !afterAllFound {
					afterAll = method.Func
					afterAllFound = true
					continue
				}
			}
			if ok, _ := regexp.MatchString("^Before", method.Name); ok {
				before = method.Func
			}
			if ok, _ := regexp.MatchString("^After", method.Name); ok {
				after = method.Func
			}
		}

		if beforeAll.IsValid() {
			beforeAll.Call([]reflect.Value{reflect.ValueOf(s)})
		}

		for i := 0; i < iType.NumMethod(); i++ {
			method := iType.Method(i)

			if ok, _ := regexp.MatchString(formatter.AllowedMethodsPattern(), method.Name); ok {

				s.SetStatus(STATUS_PASS)

				if before.IsValid() {
					before.Call([]reflect.Value{reflect.ValueOf(s)})
				}

				method.Func.Call([]reflect.Value{reflect.ValueOf(s)})

				if after.IsValid() {
					after.Call([]reflect.Value{reflect.ValueOf(s)})
				}

				switch s.GetStatus() {
				case STATUS_PASS:
					totalPassed++
				case STATUS_FAIL:
					totalFailed++
				case STATUS_PENDING:
					totalPending++
				}

				formatter.PrintStatus(s.GetStatus(), s.GetInfo())

			}

		}

		if afterAll.IsValid() {
			afterAll.Call([]reflect.Value{reflect.ValueOf(s)})
		}
	}

	formatter.PrintFinalReport(totalPassed, totalFailed, totalPending)
}
<|endoftext|>


<commit_before>package GoPool

import (
	"sync"
	"sync/atomic"

	"github.com/6xiao/go/Common"
	"time"
)

/*
eg:
type Calc struct {
	in chan int
}

func (this *Calc) Run() (interface{}, error) {
	sum := 0
	for i := range this.in {
		sum += i
	}
	return sum, nil
}

func (this *Calc) Quit(_ *GoPool.Pool, res interface{}, _ error) {
	fmt.Println("get sum", res)
}

func AtQuit(_ *GoPool.Pool, res interface{}, _ error) {
	fmt.Println("get sum", res)
}

func main() {
	intChan := make(chan int)
	calc := Calc{intChan}
	pool := GoPool.FromRunner(3, &calc)
	//pool := GoPool.NewPool(3, calc.Run, AtQuit)
	pool.Keepalive()
	fmt.Println("worker number:", pool.Count())

	for i := 0; i < 1024*1024; i++ {
		intChan <- i
	}
	pool.AddExecutor()
	fmt.Println("worker number:", pool.Count())

	close(intChan)

	pool.WaitAllQuit()
	fmt.Println("worker number:", pool.Count())
}
*/

type Runner interface {
	Run() (interface{}, error)
	Quit(*Pool, interface{}, error)
}

// goroutine pool
type Pool struct {
	sync.Mutex
	sync.WaitGroup

	count int64
	capa  int64
	run   func() (interface{}, error)
	quit  func(*Pool, interface{}, error)
}

func NewPool(capa int,
	run func() (interface{}, error),
	quit func(*Pool, interface{}, error)) *Pool {
	if capa <= 0 || run == nil {
		return nil
	}
	return &Pool{sync.Mutex{}, sync.WaitGroup{}, 0, int64(capa), run, quit}
}

func FromRunner(capa int, runner Runner) *Pool {
	return NewPool(capa, runner.Run, runner.Quit)
}

// count may great then capa when user AddExecutor
func (this *Pool) Count() int {
	return int(atomic.LoadInt64(&this.count))
}

func (this *Pool) Capacity() int {
	return int(this.capa)
}

// return after all goroutine quit in pool
func (this *Pool) WaitAllQuit() {
	this.Wait()
}

func (this *Pool) AutoKeepalive(duration time.Duration) {
	go this.autoKeepalive(duration)
}

func (this *Pool) autoKeepalive(duration time.Duration) {
	defer Common.CheckPanic()

	for {
		this.Keepalive()
		time.Sleep(duration)
	}
}

// check alive
func (this *Pool) Keepalive() int {
	defer Common.CheckPanic()
	this.Lock()
	defer this.Unlock()

	sub := int(this.capa - atomic.LoadInt64(&this.count))
	for i := 0; i < sub; i++ {
		this.AddExecutor()
	}

	return sub
}

// add goroutine manual
func (this *Pool) AddExecutor() {
	defer Common.CheckPanic()
	wg := sync.WaitGroup{}
	wg.Add(1)
	go this.executor(&wg)
	wg.Wait()
}

func (this *Pool) executor(wg *sync.WaitGroup) {
	defer Common.CheckPanic()
	this.Add(1)
	defer this.Done()
	atomic.AddInt64(&this.count, 1)
	defer atomic.AddInt64(&this.count, -1)
	wg.Done()

	result, err := this.run()
	if this.quit != nil {
		this.quit(this, result, err)
	}
}
<commit_msg>remove Capacity<commit_after>package GoPool

import (
	"sync"
	"sync/atomic"

	"github.com/6xiao/go/Common"
	"time"
)

/*
eg:
type Calc struct {
	in chan int
}

func (this *Calc) Run() (interface{}, error) {
	sum := 0
	for i := range this.in {
		sum += i
	}
	return sum, nil
}

func (this *Calc) Quit(_ *GoPool.Pool, res interface{}, _ error) {
	fmt.Println("get sum", res)
}

func AtQuit(_ *GoPool.Pool, res interface{}, _ error) {
	fmt.Println("get sum", res)
}

func main() {
	intChan := make(chan int)
	calc := Calc{intChan}
	pool := GoPool.FromRunner(3, &calc)
	//pool := GoPool.NewPool(3, calc.Run, AtQuit)
	pool.Keepalive()
	fmt.Println("worker number:", pool.Count())

	for i := 0; i < 1024*1024; i++ {
		intChan <- i
	}
	pool.AddExecutor()
	fmt.Println("worker number:", pool.Count())

	close(intChan)

	pool.WaitAllQuit()
	fmt.Println("worker number:", pool.Count())
}
*/

type Runner interface {
	Run() (interface{}, error)
	Quit(*Pool, interface{}, error)
}

// goroutine pool
type Pool struct {
	sync.Mutex
	sync.WaitGroup

	count int64
	capa  int64
	run   func() (interface{}, error)
	quit  func(*Pool, interface{}, error)
}

func NewPool(capa int,
	run func() (interface{}, error),
	quit func(*Pool, interface{}, error)) *Pool {
	if capa <= 0 || run == nil {
		return nil
	}
	return &Pool{sync.Mutex{}, sync.WaitGroup{}, 0, int64(capa), run, quit}
}

func FromRunner(capa int, runner Runner) *Pool {
	return NewPool(capa, runner.Run, runner.Quit)
}

// count may great then capa when user AddExecutor
func (this *Pool) Count() int {
	return int(atomic.LoadInt64(&this.count))
}

// return after all goroutine quit in pool
func (this *Pool) WaitAllQuit() {
	this.Wait()
}

func (this *Pool) AutoKeepalive(duration time.Duration) {
	go this.autoKeepalive(duration)
}

func (this *Pool) autoKeepalive(duration time.Duration) {
	defer Common.CheckPanic()

	for {
		this.Keepalive()
		time.Sleep(duration)
	}
}

// check alive
func (this *Pool) Keepalive() int {
	defer Common.CheckPanic()
	this.Lock()
	defer this.Unlock()

	sub := int(this.capa - atomic.LoadInt64(&this.count))
	for i := 0; i < sub; i++ {
		this.AddExecutor()
	}

	return sub
}

// add goroutine manual
func (this *Pool) AddExecutor() {
	defer Common.CheckPanic()
	wg := sync.WaitGroup{}
	wg.Add(1)
	go this.executor(&wg)
	wg.Wait()
}

func (this *Pool) executor(wg *sync.WaitGroup) {
	defer Common.CheckPanic()
	this.Add(1)
	defer this.Done()
	atomic.AddInt64(&this.count, 1)
	defer atomic.AddInt64(&this.count, -1)
	wg.Done()

	result, err := this.run()
	if this.quit != nil {
		this.quit(this, result, err)
	}
}
<|endoftext|>


<commit_before>package autonat

import (
	"context"
	"net"
	"testing"
	"time"

	libp2p "github.com/libp2p/go-libp2p"
	autonat "github.com/libp2p/go-libp2p-autonat"
	host "github.com/libp2p/go-libp2p-host"
	pstore "github.com/libp2p/go-libp2p-peerstore"
	manet "github.com/multiformats/go-multiaddr-net"
)

func makeAutoNATService(ctx context.Context, t *testing.T) (host.Host, *AutoNATService) {
	h, err := libp2p.New(ctx, libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"))
	if err != nil {
		t.Fatal(err)
	}

	as, err := NewAutoNATService(ctx, h)
	if err != nil {
		t.Fatal(err)
	}

	return h, as
}

func makeAutoNATClient(ctx context.Context, t *testing.T) (host.Host, autonat.AutoNATClient) {
	h, err := libp2p.New(ctx, libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"))
	if err != nil {
		t.Fatal(err)
	}

	cli := autonat.NewAutoNATClient(h)
	return h, cli
}

func connect(t *testing.T, a, b host.Host) {
	pinfo := pstore.PeerInfo{ID: a.ID(), Addrs: a.Addrs()}
	err := b.Connect(context.Background(), pinfo)
	if err != nil {
		t.Fatal(err)
	}
}

// Note: these tests assume that the host has only private inet addresses!
func TestAutoNATServiceDialError(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	save := AutoNATServiceDialTimeout
	AutoNATServiceDialTimeout = 1 * time.Second

	hs, _ := makeAutoNATService(ctx, t)
	hc, ac := makeAutoNATClient(ctx, t)
	connect(t, hs, hc)

	_, err := ac.DialBack(ctx, hs.ID())
	if err == nil {
		t.Fatal("Dial back succeeded unexpectedly!")
	}

	if !autonat.IsDialError(err) {
		t.Fatal(err)
	}

	AutoNATServiceDialTimeout = save
}

func TestAutoNATServiceDialSuccess(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	save := manet.Private4
	manet.Private4 = []*net.IPNet{}

	hs, _ := makeAutoNATService(ctx, t)
	hc, ac := makeAutoNATClient(ctx, t)
	connect(t, hs, hc)

	_, err := ac.DialBack(ctx, hs.ID())
	if err != nil {
		t.Fatalf("Dial back failed: %s", err.Error())
	}

	manet.Private4 = save
}

func TestAutoNATServiceDialRateLimiter(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	save1 := AutoNATServiceDialTimeout
	AutoNATServiceDialTimeout = 1 * time.Second
	save2 := AutoNATServiceResetInterval
	AutoNATServiceResetInterval = 1 * time.Second
	save3 := AutoNATServiceThrottle
	AutoNATServiceThrottle = 1
	save4 := manet.Private4
	manet.Private4 = []*net.IPNet{}

	hs, _ := makeAutoNATService(ctx, t)
	hc, ac := makeAutoNATClient(ctx, t)
	connect(t, hs, hc)

	_, err := ac.DialBack(ctx, hs.ID())
	if err != nil {
		t.Fatal(err)
	}

	_, err = ac.DialBack(ctx, hs.ID())
	if err == nil {
		t.Fatal("Dial back succeeded unexpectedly!")
	}

	if !autonat.IsDialRefused(err) {
		t.Fatal(err)
	}

	time.Sleep(2 * time.Second)

	_, err = ac.DialBack(ctx, hs.ID())
	if err != nil {
		t.Fatal(err)
	}

	AutoNATServiceDialTimeout = save1
	AutoNATServiceResetInterval = save2
	AutoNATServiceThrottle = save3
	manet.Private4 = save4
}
<commit_msg>update test for AutoNATClient constructor change<commit_after>package autonat

import (
	"context"
	"net"
	"testing"
	"time"

	libp2p "github.com/libp2p/go-libp2p"
	autonat "github.com/libp2p/go-libp2p-autonat"
	host "github.com/libp2p/go-libp2p-host"
	pstore "github.com/libp2p/go-libp2p-peerstore"
	manet "github.com/multiformats/go-multiaddr-net"
)

func makeAutoNATService(ctx context.Context, t *testing.T) (host.Host, *AutoNATService) {
	h, err := libp2p.New(ctx, libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"))
	if err != nil {
		t.Fatal(err)
	}

	as, err := NewAutoNATService(ctx, h)
	if err != nil {
		t.Fatal(err)
	}

	return h, as
}

func makeAutoNATClient(ctx context.Context, t *testing.T) (host.Host, autonat.AutoNATClient) {
	h, err := libp2p.New(ctx, libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"))
	if err != nil {
		t.Fatal(err)
	}

	cli := autonat.NewAutoNATClient(h, nil)
	return h, cli
}

func connect(t *testing.T, a, b host.Host) {
	pinfo := pstore.PeerInfo{ID: a.ID(), Addrs: a.Addrs()}
	err := b.Connect(context.Background(), pinfo)
	if err != nil {
		t.Fatal(err)
	}
}

// Note: these tests assume that the host has only private inet addresses!
func TestAutoNATServiceDialError(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	save := AutoNATServiceDialTimeout
	AutoNATServiceDialTimeout = 1 * time.Second

	hs, _ := makeAutoNATService(ctx, t)
	hc, ac := makeAutoNATClient(ctx, t)
	connect(t, hs, hc)

	_, err := ac.DialBack(ctx, hs.ID())
	if err == nil {
		t.Fatal("Dial back succeeded unexpectedly!")
	}

	if !autonat.IsDialError(err) {
		t.Fatal(err)
	}

	AutoNATServiceDialTimeout = save
}

func TestAutoNATServiceDialSuccess(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	save := manet.Private4
	manet.Private4 = []*net.IPNet{}

	hs, _ := makeAutoNATService(ctx, t)
	hc, ac := makeAutoNATClient(ctx, t)
	connect(t, hs, hc)

	_, err := ac.DialBack(ctx, hs.ID())
	if err != nil {
		t.Fatalf("Dial back failed: %s", err.Error())
	}

	manet.Private4 = save
}

func TestAutoNATServiceDialRateLimiter(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	save1 := AutoNATServiceDialTimeout
	AutoNATServiceDialTimeout = 1 * time.Second
	save2 := AutoNATServiceResetInterval
	AutoNATServiceResetInterval = 1 * time.Second
	save3 := AutoNATServiceThrottle
	AutoNATServiceThrottle = 1
	save4 := manet.Private4
	manet.Private4 = []*net.IPNet{}

	hs, _ := makeAutoNATService(ctx, t)
	hc, ac := makeAutoNATClient(ctx, t)
	connect(t, hs, hc)

	_, err := ac.DialBack(ctx, hs.ID())
	if err != nil {
		t.Fatal(err)
	}

	_, err = ac.DialBack(ctx, hs.ID())
	if err == nil {
		t.Fatal("Dial back succeeded unexpectedly!")
	}

	if !autonat.IsDialRefused(err) {
		t.Fatal(err)
	}

	time.Sleep(2 * time.Second)

	_, err = ac.DialBack(ctx, hs.ID())
	if err != nil {
		t.Fatal(err)
	}

	AutoNATServiceDialTimeout = save1
	AutoNATServiceResetInterval = save2
	AutoNATServiceThrottle = save3
	manet.Private4 = save4
}
<|endoftext|>