<commit_before>package kping

import (
	"context"
	"fmt"
	"net"
	"os"
	"sync"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pfring"
	"golang.org/x/net/ipv4"
)

type ipEvent struct {
	ip           string
	seq          int
	sendDuration time.Duration
	recvRTT      time.Duration
}

// Statistic ping statistic of IP
type Statistic struct {
	RecvNum   int64     // recv packets number
	SentNum   int64     // sent packets number
	LostNum   float64   // lost packets number
	RTTs      []float64 // RTT of each recv packet
	MinRTT    float64   // minimum RTT of RTTs
	MaxRTT    float64   // maxmum RTT of RTTs
	AvgRTT    float64   // average RTT of RTTs
	StdDevRTT float64   // stddev of RTTs

	ipEvents map[int]ipEvent // key: ICMP seq
}

// DefaultRecvMode default recv mode
var DefaultRecvMode = "afpacket"

// Options represent options
type Options interface{}

type sendOptions struct {
	BatchSize   int64
	BufferSize  int64
	Parallel    int64
	Timeout     time.Duration
	WaitTimeout time.Duration
}

var defaultSendOptions = sendOptions{
	BatchSize:   1024,
	BufferSize:  10 * 1024 * 1024,
	Parallel:    30,
	Timeout:     100 * time.Second,
	WaitTimeout: 20 * time.Millisecond,
}

// SendOptions batch send options
//   batchSize: batch send ICMP packet number, must <= 1024, default: 1024
// 	 bufferSize: batch send buffer size, default: 10MB
// 	 parallel: send goroutine number, default: 30
// 	 timeout: send timeout, default: 100s
// 	 waitTimeout: batch send interval, default: 20ms
func SendOptions(batchSize, bufferSize, parallel int64, timeout, waitTimeout time.Duration) (options Options, err error) {
	return sendOptions{
		BatchSize:   batchSize,
		BufferSize:  bufferSize,
		Parallel:    parallel,
		Timeout:     timeout,
		WaitTimeout: waitTimeout,
	}, nil
}

type batchRecvOptions struct {
	BatchSize  int64
	BufferSize int64
	Parallel   int64
	Timeout    time.Duration
}

var defaultBatchRecvOptions = batchRecvOptions{
	BatchSize:  100,
	BufferSize: 10 * 1024 * 1024,
	Parallel:   10,
	Timeout:    100 * time.Millisecond,
}

// BatchRecvOptions batch recv options
//   batchSize: batch recv ICMP packet number, must <= 1024, default: 100
//   bufferSize: batch recv buffer size, default: 10MB
//   parallel: recv goroutine number, default: 10
//   timeout: recv timeout, default: 100ms
func BatchRecvOptions(batchSize, bufferSize, parallel int64, timeout time.Duration) (options Options, err error) {
	return batchRecvOptions{
		BatchSize:  batchSize,
		BufferSize: bufferSize,
		Parallel:   parallel,
		Timeout:    timeout,
	}, nil
}

type afpacketRecvOptions struct {
	Parallel   int64
	BlockMB    int64
	Timeout    time.Duration
	Iface      string
	SnapLength int64
}

var defaultAfPacketRecvOptions = afpacketRecvOptions{
	Parallel:   1,
	BlockMB:    128,
	Timeout:    100 * time.Millisecond,
	Iface:      "eth0",
	SnapLength: 128,
}

// AfPacketRecvOptions af_packet recv options
//   parallel: recv goroutine number, default: 1
//   blockMB: af_packet: total block size, default: 128MB
//   timeout: af_packet: poll timeout, default: 100ms
//   iface:  recv interface name, default: eth0
//   snapLength: snap byte number, default: 128B
func AfPacketRecvOptions(parallel, blockMB, snapLength int64, iface string, timeout time.Duration) (options Options, err error) {
	return afpacketRecvOptions{
		Parallel:   parallel,
		BlockMB:    blockMB,
		Timeout:    timeout,
		Iface:      iface,
		SnapLength: snapLength,
	}, nil
}

type pfringRecvOptions struct {
	Iface      string
	SnapLength int64
	Parallel   int64
}

var defaultPFRingRecvOptions = pfringRecvOptions{
	Iface:      "eth0",
	SnapLength: 128,
	Parallel:   1,
}

// PFRingRecvOptions pf_ring recv options
//   parallel: recv goroutine number， default: 1
//   snapLength: snap byte number, default: 128B
//   iface: recv interface name, default: eth0
func PFRingRecvOptions(parallel, snapLength int64, iface string) (options Options, err error) {
	return pfringRecvOptions{
		Iface:      iface,
		SnapLength: snapLength,
		Parallel:   parallel,
	}, nil
}

// Pinger repsent kping methods
type Pinger interface {
	// SetRecvMode set recv mode, oneof: afpacket(default)|batch|pfring
	SetRecvMode(recvMode string) error
	// SetOptions set send or recv options
	SetOptions(options Options) error
	// AddIPs add IP addrs to pinger
	AddIPs(addrs []string) error
	// Run flood ping, then calculate statistic of each IP
	Run() (statistics map[string]*Statistic, err error)
}

// NewPinger return a new pinger
func NewPinger(sourceIP string, count, size int64, timeout, interval time.Duration) (p Pinger, err error) {
	p = &kping{
		sourceIP:         sourceIP,
		count:            count,
		size:             size,
		timeout:          timeout,
		interval:         interval,
		recvMode:         DefaultRecvMode,
		sendOpts:         defaultSendOptions,
		afpacketRecvOpts: defaultAfPacketRecvOptions,
		batchRecvOpts:    defaultBatchRecvOptions,
		pfringRecvOpts:   defaultPFRingRecvOptions,
		recvReady:        make(chan bool),
		sendDone:         make(chan bool),
		sendLock:         new(sync.Mutex),
	}
	return p, nil
}

type kping struct {
	sourceIP string        // ping source IP
	count    int64         // ping count, must < 55536
	size     int64         // ping ICMP packet payload bytes, must > 8
	timeout  time.Duration // ping total timeout
	interval time.Duration // ping interval
	recvMode string

	sendOpts         sendOptions
	afpacketRecvOpts afpacketRecvOptions
	batchRecvOpts    batchRecvOptions
	pfringRecvOpts   pfringRecvOptions

	rawConn      *rawConn
	ring         *pfring.Ring
	packetSource *gopacket.PacketSource
	stats        map[string]*Statistic // key: ip
	addrs        []*net.IPAddr
	ipCount      int64
	context      context.Context
	cancel       context.CancelFunc
	recvReady    chan bool
	sendDone     chan bool
	sendLock     *sync.Mutex
	ipEventChan  chan *ipEvent
}

func (p *kping) SetRecvMode(mode string) (err error) {
	switch mode {
	case "afpacket", "pfring", "batch":
		p.recvMode = mode
	default:
		return fmt.Errorf("unknown recv mode: %s, should be oneof: afpacket|pfring|batch", p.recvMode)
	}
	return nil
}

func (p *kping) SetOptions(options Options) (err error) {
	switch opts := options.(type) {
	case sendOptions:
		p.sendOpts = opts
	case batchRecvOptions:
		p.batchRecvOpts = opts
	case afpacketRecvOptions:
		p.afpacketRecvOpts = opts
	case pfringRecvOptions:
		p.pfringRecvOpts = opts
	}
	return nil
}

func (p *kping) AddIPs(ipaddrs []string) error {
	p.addrs = make([]*net.IPAddr, 0, len(ipaddrs))
	p.stats = make(map[string]*Statistic, len(ipaddrs))
	for _, ipaddr := range ipaddrs {
		addr, err := net.ResolveIPAddr("ip4", ipaddr)
		if err != nil {
			return fmt.Errorf("invalid IP: %s", ipaddr)
		}
		p.addrs = append(p.addrs, addr)
		p.ipCount++
	}
	return nil
}

type addrBatch struct {
	seq   int
	addrs []*net.IPAddr
}

func (p *kping) Run() (statistics map[string]*Statistic, err error) {
	// used by send & recv, so buffer size is double
	p.ipEventChan = make(chan *ipEvent, p.ipCount*p.count*2)

	// set context
	ctx, cancel := context.WithTimeout(context.TODO(), p.timeout)
	p.context = ctx
	p.cancel = cancel

	// create raw socket connection
	rawConn, err := newRawConn(p.sourceIP, p.batchRecvOpts.BufferSize, p.sendOpts.BufferSize, p.batchRecvOpts.Timeout, p.sendOpts.Timeout)
	if err != nil {
		return nil, err
	}
	defer rawConn.close()

	if p.recvMode == "batch" {
		// filter ICMP Echo & Reply type packet
		filter := ipv4.ICMPFilter{}
		filter.SetAll(false)
		filter.Accept(ipv4.ICMPTypeEchoReply)
		if err := rawConn.setICMPFilter(&filter); err != nil {
			return nil, fmt.Errorf("setICMPFilter failed: %v", err)
		}
	} else if p.recvMode == "pfring" {
		ring, err := pfring.NewRing(p.pfringRecvOpts.Iface, uint32(p.pfringRecvOpts.SnapLength), 0)
		if err != nil {
			return nil, fmt.Errorf("pfring: NewRing failed: %v", err)
		}
		filter := fmt.Sprintf("ip and dst %s and icmp[icmptype] = icmp-echoreply and icmp[4:2] > %d and icmp[6:2] > %d", p.sourceIP, icmpIDSeqInitNum, icmpIDSeqInitNum)
		if err := ring.SetBPFFilter(filter); err != nil {
			return nil, fmt.Errorf("pfring: set bpf filter failed: %v, filter: %s", err, filter)
		}
		if err := ring.SetSocketMode(pfring.ReadOnly); err != nil {
			return nil, fmt.Errorf("pfring: set socket mode failed: %v", err)
		}
		if err := ring.SetDirection(pfring.ReceiveOnly); err != nil {
			return nil, fmt.Errorf("pfring: set direction failed: %v", err)
		}
		if err := ring.Enable(); err != nil {
			return nil, fmt.Errorf("pfring: enable failed: %v", err)
		}
		p.ring = ring
		defer p.ring.Close()

		packetSource := gopacket.NewPacketSource(p.ring, layers.LinkTypeEthernet)
		packetSource.NoCopy = true
		p.packetSource = packetSource
	}

	// receive packets
	go func() {
		defer close(p.ipEventChan)

		fmt.Fprintf(os.Stderr, "kping recv: started, ipCount: %d\n", p.ipCount)
		wg := new(sync.WaitGroup)
		stime := time.Now()

		var recvParallel int64
		var recvFunc func(index int, wg *sync.WaitGroup)
		switch p.recvMode {
		case "afpacket":
			recvParallel = p.afpacketRecvOpts.Parallel
			recvFunc = p.afpacketRecv
		case "pfring":
			recvParallel = p.pfringRecvOpts.Parallel
			recvFunc = p.pfringRecv
		case "batch":
			recvParallel = p.batchRecvOpts.Parallel
			recvFunc = p.batchRecv
		default:
			panic(fmt.Sprintf("ping recv: unknown recvMode: %s", p.recvMode))

		}
		for i := 0; i < int(recvParallel); i++ {
			wg.Add(1)
			index := i
			go recvFunc(index, wg)
		}

		// receive ready
		close(p.recvReady)

		wg.Wait()
		fmt.Fprintf(os.Stderr, "kping recv: all done, ipCount: %d, usedTime: %s\n", p.ipCount, time.Since(stime))
	}()

	// send packets
	go func() {
		defer p.cancel()
		defer close(p.sendDone)

		// wait receive ready
		<-p.recvReady

		stime := time.Now()
		addrBatchChan := make(chan addrBatch)
		fmt.Fprintf(os.Stderr, "kping send: started, ipCount: %d, \n", p.ipCount)

		// cocurenccy send packets
		for i := 0; i < int(p.sendOpts.Parallel); i++ {
			index := i
			go p.send(index, addrBatchChan) // after close addrBatchChan, goroutine return
		}

		// caculate batch number
		var batchNum = 0
		if p.ipCount%p.sendOpts.BatchSize == 0 {
			batchNum = int(p.ipCount / p.sendOpts.BatchSize)
		} else {
			batchNum = int(p.ipCount/p.sendOpts.BatchSize + 1)
		}

		// fill address for each batch
		addrBatchs := make([]addrBatch, batchNum)
		for i := range addrBatchs {
			addrBatchs[i] = addrBatch{
				addrs: make([]*net.IPAddr, 0, p.sendOpts.BatchSize),
			}
		}
		for i, addr := range p.addrs {
			j := i / int(p.sendOpts.BatchSize)
			batch := addrBatchs[j]
			batch.addrs = append(batch.addrs, addr)
			addrBatchs[j] = batch
		}

		// send extra 10 packets
		for n := 0; n < int(p.count+10); n++ {
			stime := time.Now()
			for _, batch := range addrBatchs {
				batch.seq = n
				addrBatchChan <- batch
			}
			time.Sleep(p.interval)
			fmt.Fprintf(os.Stderr, "kping send: seq %d(%d) done, usedTime: %s\n", n, p.count+10, time.Since(stime))
		}

		// sent done, sleep 1s
		close(addrBatchChan)
		fmt.Fprintf(os.Stderr, "kping send: all done, ipCount: %d, usedTime: %s\n", p.ipCount, time.Since(stime))
		time.Sleep(1 * time.Second)
	}()

	p.process()
	statistics = p.statistic()
	return statistics, nil
}
<commit_msg>refine comment<commit_after>package kping

import (
	"context"
	"fmt"
	"net"
	"os"
	"sync"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pfring"
	"golang.org/x/net/ipv4"
)

type ipEvent struct {
	ip           string
	seq          int
	sendDuration time.Duration
	recvRTT      time.Duration
}

// A Statistic is a ping statistic of IP
type Statistic struct {
	RecvNum   int64     // recv packets number
	SentNum   int64     // sent packets number
	LostNum   float64   // lost packets number
	RTTs      []float64 // RTT of each recv packet
	MinRTT    float64   // minimum RTT of RTTs
	MaxRTT    float64   // maxmum RTT of RTTs
	AvgRTT    float64   // average RTT of RTTs
	StdDevRTT float64   // stddev of RTTs

	ipEvents map[int]ipEvent // key: ICMP seq
}

// DefaultRecvMode is the default recv mode
var DefaultRecvMode = "afpacket"

// Options representes send & recv options
type Options interface{}

type sendOptions struct {
	BatchSize   int64
	BufferSize  int64
	Parallel    int64
	Timeout     time.Duration
	WaitTimeout time.Duration
}

var defaultSendOptions = sendOptions{
	BatchSize:   1024,
	BufferSize:  10 * 1024 * 1024,
	Parallel:    30,
	Timeout:     100 * time.Second,
	WaitTimeout: 20 * time.Millisecond,
}

// SendOptions creates batch send options
//   batchSize: batch send ICMP packet number, must <= 1024, default: 1024
//   bufferSize: batch send buffer size, default: 10MB
//   parallel: send goroutine number, default: 30
//   timeout: send timeout, default: 100s
//   waitTimeout: batch send interval, default: 20ms
func SendOptions(batchSize, bufferSize, parallel int64, timeout, waitTimeout time.Duration) (options Options, err error) {
	return sendOptions{
		BatchSize:   batchSize,
		BufferSize:  bufferSize,
		Parallel:    parallel,
		Timeout:     timeout,
		WaitTimeout: waitTimeout,
	}, nil
}

type batchRecvOptions struct {
	BatchSize  int64
	BufferSize int64
	Parallel   int64
	Timeout    time.Duration
}

var defaultBatchRecvOptions = batchRecvOptions{
	BatchSize:  100,
	BufferSize: 10 * 1024 * 1024,
	Parallel:   10,
	Timeout:    100 * time.Millisecond,
}

// BatchRecvOptions creates batch recv options
//   batchSize: batch recv ICMP packet number, must <= 1024, default: 100
//   bufferSize: batch recv buffer size, default: 10MB
//   parallel: recv goroutine number, default: 10
//   timeout: recv timeout, default: 100ms
func BatchRecvOptions(batchSize, bufferSize, parallel int64, timeout time.Duration) (options Options, err error) {
	return batchRecvOptions{
		BatchSize:  batchSize,
		BufferSize: bufferSize,
		Parallel:   parallel,
		Timeout:    timeout,
	}, nil
}

type afpacketRecvOptions struct {
	Parallel   int64
	BlockMB    int64
	Timeout    time.Duration
	Iface      string
	SnapLength int64
}

var defaultAfPacketRecvOptions = afpacketRecvOptions{
	Parallel:   1,
	BlockMB:    128,
	Timeout:    100 * time.Millisecond,
	Iface:      "eth0",
	SnapLength: 128,
}

// AfPacketRecvOptions creates af_packet recv options
//   parallel: recv goroutine number, default: 1
//   blockMB: af_packet: total block size, default: 128MB
//   timeout: af_packet: poll timeout, default: 100ms
//   iface:  recv interface name, default: eth0
//   snapLength: snap byte number, default: 128B
func AfPacketRecvOptions(parallel, blockMB, snapLength int64, iface string, timeout time.Duration) (options Options, err error) {
	return afpacketRecvOptions{
		Parallel:   parallel,
		BlockMB:    blockMB,
		Timeout:    timeout,
		Iface:      iface,
		SnapLength: snapLength,
	}, nil
}

type pfringRecvOptions struct {
	Iface      string
	SnapLength int64
	Parallel   int64
}

var defaultPFRingRecvOptions = pfringRecvOptions{
	Iface:      "eth0",
	SnapLength: 128,
	Parallel:   1,
}

// PFRingRecvOptions creates pf_ring recv options
//   parallel: recv goroutine number， default: 1
//   snapLength: snap byte number, default: 128B
//   iface: recv interface name, default: eth0
func PFRingRecvOptions(parallel, snapLength int64, iface string) (options Options, err error) {
	return pfringRecvOptions{
		Iface:      iface,
		SnapLength: snapLength,
		Parallel:   parallel,
	}, nil
}

// A Pinger provides various methods of kping
type Pinger interface {
	// SetRecvMode set recv mode, oneof: afpacket(default)|batch|pfring
	SetRecvMode(recvMode string) error
	// SetOptions set send or recv options
	SetOptions(options Options) error
	// AddIPs add IP addrs to pinger
	AddIPs(addrs []string) error
	// Run flood ping, then calculate statistic of each IP
	Run() (statistics map[string]*Statistic, err error)
}

// NewPinger returns a new pinger
func NewPinger(sourceIP string, count, size int64, timeout, interval time.Duration) (p Pinger, err error) {
	p = &kping{
		sourceIP:         sourceIP,
		count:            count,
		size:             size,
		timeout:          timeout,
		interval:         interval,
		recvMode:         DefaultRecvMode,
		sendOpts:         defaultSendOptions,
		afpacketRecvOpts: defaultAfPacketRecvOptions,
		batchRecvOpts:    defaultBatchRecvOptions,
		pfringRecvOpts:   defaultPFRingRecvOptions,
		recvReady:        make(chan bool),
		sendDone:         make(chan bool),
		sendLock:         new(sync.Mutex),
	}
	return p, nil
}

type kping struct {
	sourceIP string        // ping source IP
	count    int64         // ping count, must < 55536
	size     int64         // ping ICMP packet payload bytes, must > 8
	timeout  time.Duration // ping total timeout
	interval time.Duration // ping interval
	recvMode string

	sendOpts         sendOptions
	afpacketRecvOpts afpacketRecvOptions
	batchRecvOpts    batchRecvOptions
	pfringRecvOpts   pfringRecvOptions

	rawConn      *rawConn
	ring         *pfring.Ring
	packetSource *gopacket.PacketSource
	stats        map[string]*Statistic // key: ip
	addrs        []*net.IPAddr
	ipCount      int64
	context      context.Context
	cancel       context.CancelFunc
	recvReady    chan bool
	sendDone     chan bool
	sendLock     *sync.Mutex
	ipEventChan  chan *ipEvent
}

func (p *kping) SetRecvMode(mode string) (err error) {
	switch mode {
	case "afpacket", "pfring", "batch":
		p.recvMode = mode
	default:
		return fmt.Errorf("unknown recv mode: %s, should be oneof: afpacket|pfring|batch", p.recvMode)
	}
	return nil
}

func (p *kping) SetOptions(options Options) (err error) {
	switch opts := options.(type) {
	case sendOptions:
		p.sendOpts = opts
	case batchRecvOptions:
		p.batchRecvOpts = opts
	case afpacketRecvOptions:
		p.afpacketRecvOpts = opts
	case pfringRecvOptions:
		p.pfringRecvOpts = opts
	}
	return nil
}

func (p *kping) AddIPs(ipaddrs []string) error {
	p.addrs = make([]*net.IPAddr, 0, len(ipaddrs))
	p.stats = make(map[string]*Statistic, len(ipaddrs))
	for _, ipaddr := range ipaddrs {
		addr, err := net.ResolveIPAddr("ip4", ipaddr)
		if err != nil {
			return fmt.Errorf("invalid IP: %s", ipaddr)
		}
		p.addrs = append(p.addrs, addr)
		p.ipCount++
	}
	return nil
}

type addrBatch struct {
	seq   int
	addrs []*net.IPAddr
}

func (p *kping) Run() (statistics map[string]*Statistic, err error) {
	// used by send & recv, so buffer size is double
	p.ipEventChan = make(chan *ipEvent, p.ipCount*p.count*2)

	// set context
	ctx, cancel := context.WithTimeout(context.TODO(), p.timeout)
	p.context = ctx
	p.cancel = cancel

	// create raw socket connection
	rawConn, err := newRawConn(p.sourceIP, p.batchRecvOpts.BufferSize, p.sendOpts.BufferSize, p.batchRecvOpts.Timeout, p.sendOpts.Timeout)
	if err != nil {
		return nil, err
	}
	defer rawConn.close()

	if p.recvMode == "batch" {
		// filter ICMP Echo & Reply type packet
		filter := ipv4.ICMPFilter{}
		filter.SetAll(false)
		filter.Accept(ipv4.ICMPTypeEchoReply)
		if err := rawConn.setICMPFilter(&filter); err != nil {
			return nil, fmt.Errorf("setICMPFilter failed: %v", err)
		}
	} else if p.recvMode == "pfring" {
		ring, err := pfring.NewRing(p.pfringRecvOpts.Iface, uint32(p.pfringRecvOpts.SnapLength), 0)
		if err != nil {
			return nil, fmt.Errorf("pfring: NewRing failed: %v", err)
		}
		filter := fmt.Sprintf("ip and dst %s and icmp[icmptype] = icmp-echoreply and icmp[4:2] > %d and icmp[6:2] > %d", p.sourceIP, icmpIDSeqInitNum, icmpIDSeqInitNum)
		if err := ring.SetBPFFilter(filter); err != nil {
			return nil, fmt.Errorf("pfring: set bpf filter failed: %v, filter: %s", err, filter)
		}
		if err := ring.SetSocketMode(pfring.ReadOnly); err != nil {
			return nil, fmt.Errorf("pfring: set socket mode failed: %v", err)
		}
		if err := ring.SetDirection(pfring.ReceiveOnly); err != nil {
			return nil, fmt.Errorf("pfring: set direction failed: %v", err)
		}
		if err := ring.Enable(); err != nil {
			return nil, fmt.Errorf("pfring: enable failed: %v", err)
		}
		p.ring = ring
		defer p.ring.Close()

		packetSource := gopacket.NewPacketSource(p.ring, layers.LinkTypeEthernet)
		packetSource.NoCopy = true
		p.packetSource = packetSource
	}

	// receive packets
	go func() {
		defer close(p.ipEventChan)

		fmt.Fprintf(os.Stderr, "kping recv: started, ipCount: %d\n", p.ipCount)
		wg := new(sync.WaitGroup)
		stime := time.Now()

		var recvParallel int64
		var recvFunc func(index int, wg *sync.WaitGroup)
		switch p.recvMode {
		case "afpacket":
			recvParallel = p.afpacketRecvOpts.Parallel
			recvFunc = p.afpacketRecv
		case "pfring":
			recvParallel = p.pfringRecvOpts.Parallel
			recvFunc = p.pfringRecv
		case "batch":
			recvParallel = p.batchRecvOpts.Parallel
			recvFunc = p.batchRecv
		default:
			panic(fmt.Sprintf("ping recv: unknown recvMode: %s", p.recvMode))

		}
		for i := 0; i < int(recvParallel); i++ {
			wg.Add(1)
			index := i
			go recvFunc(index, wg)
		}

		// receive ready
		close(p.recvReady)

		wg.Wait()
		fmt.Fprintf(os.Stderr, "kping recv: all done, ipCount: %d, usedTime: %s\n", p.ipCount, time.Since(stime))
	}()

	// send packets
	go func() {
		defer p.cancel()
		defer close(p.sendDone)

		// wait receive ready
		<-p.recvReady

		stime := time.Now()
		addrBatchChan := make(chan addrBatch)
		fmt.Fprintf(os.Stderr, "kping send: started, ipCount: %d, \n", p.ipCount)

		// cocurenccy send packets
		for i := 0; i < int(p.sendOpts.Parallel); i++ {
			index := i
			go p.send(index, addrBatchChan) // after close addrBatchChan, goroutine return
		}

		// caculate batch number
		var batchNum = 0
		if p.ipCount%p.sendOpts.BatchSize == 0 {
			batchNum = int(p.ipCount / p.sendOpts.BatchSize)
		} else {
			batchNum = int(p.ipCount/p.sendOpts.BatchSize + 1)
		}

		// fill address for each batch
		addrBatchs := make([]addrBatch, batchNum)
		for i := range addrBatchs {
			addrBatchs[i] = addrBatch{
				addrs: make([]*net.IPAddr, 0, p.sendOpts.BatchSize),
			}
		}
		for i, addr := range p.addrs {
			j := i / int(p.sendOpts.BatchSize)
			batch := addrBatchs[j]
			batch.addrs = append(batch.addrs, addr)
			addrBatchs[j] = batch
		}

		// send extra 10 packets
		for n := 0; n < int(p.count+10); n++ {
			stime := time.Now()
			for _, batch := range addrBatchs {
				batch.seq = n
				addrBatchChan <- batch
			}
			time.Sleep(p.interval)
			fmt.Fprintf(os.Stderr, "kping send: seq %d(%d) done, usedTime: %s\n", n, p.count+10, time.Since(stime))
		}

		// sent done, sleep 1s
		close(addrBatchChan)
		fmt.Fprintf(os.Stderr, "kping send: all done, ipCount: %d, usedTime: %s\n", p.ipCount, time.Since(stime))
		time.Sleep(1 * time.Second)
	}()

	p.process()
	statistics = p.statistic()
	return statistics, nil
}
<|endoftext|>


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

package fn

import (
	"errors"
	"fmt"
	"log"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

func strMinWidth(str string, width int) string {
	len1 := len(str)
	if len1 < width {
		str = str + strings.Repeat(" ", width-len1)
	}
	return str
}

// fn log trace but may first need to find appropriate filename and line num
func helplt(lvl int, msg, reffile, reflnum string) (newReffile, newReflnum string) {
	var filenlr string

	// get original [current] log flags
	orgflags := logt.Flags()
	sl := log.Lshortfile | log.Llongfile
	lfn := orgflags & sl

	var ref string

	// if log flags are including filename
	if lfn > 0 {
		_, file, line, _ := runtime.Caller(lvl)
		linenum := fmt.Sprintf(":%d", line)
		if orgflags&log.Lshortfile > 0 {
			file = filepath.Base(file)
		} else {
			// log.Llongfile
			if logTraceFlags&Trfilenogps > 0 {
				if strings.HasPrefix(file, gopathsrc) {
					file = file[len(gopathsrc):]
				}
			}
		}
		newReffile = filepath.Base(file)
		newReflnum = linenum

		// seems if this is true there is a problem elsewhere
		// as in a weird invocation end portion of log trace,
		// possible by passing that portion and invoking in
		// another function which package fn does NOT support.
		if reffile != "" && reffile != newReffile {
			logt.Panic(errors.New("reffile:" + reffile + " != newReffile:" + newReffile))
		}

		if reffile != "" && logTraceFlags&Trfnobegref == 0 {
			if logTraceFlags&Trfbegrefincfile > 0 {
				ref = "<" + reffile + reflnum + ">"
			} else {
				ref = "<" + reflnum + ">"
			}
		}

		filenlr = file + linenum + ref + " "
		filenlr = strMinWidth(filenlr, logAlignFile)

		// set log flags not to include filename
		logt.SetFlags(orgflags &^ sl)
	}
	logt.Printf("%s%s", filenlr, msg)
	if lfn > 0 {
		// restore log flags
		logt.SetFlags(orgflags)
	}
	return newReffile, newReflnum
}

func formatTime(t time.Time, microseconds bool, msg string) string {
	yr, mon, dy := t.Date()
	hr, min, sec := t.Clock()
	var micro string
	if microseconds {
		micro = fmt.Sprintf(".%06d", t.Nanosecond()/1e3)
	}
	return fmt.Sprintf("%s%d/%02d/%02d %02d:%02d:%02d%s", msg, yr, mon, dy, hr, min, sec, micro)
}

func helpltend(lvladj int, trlabel string, start time.Time, begFn, reffile, reflnum, endMsg string) {
	endTime := time.Now()
	endFn := Lvl(Lgpar + lvladj)
	if begFn != endFn {
		if strings.Contains(CStk(), "<--runtime.gopanic") {
			logt.Println("GOPANIC DETECTED --exiting '"+trlabel+"'(helpltend)>CStk:", CStk())
			logt.Println("begFn:"+begFn+" != endFn:"+endFn, " reffile:", reffile, " reflnum", reflnum, "\n\n ")
			return
		}
		// if Idiomatic usage of LogTrace and LogTraceMsgs then should not have a panic.
		err := fmt.Sprintf("begFn != endFn\n begFn:%s\n endFn:%s\n  Cstk:%s \n"+
			"Panic probable cause due to end trace pairing return portion called from different func",
			begFn, endFn, CStk())
		logt.Panic(errors.New(err)) // see todo above
	}
	if endMsg != "" {
		endMsg = " " + endMsg
	}
	var str string

	muLogt.Lock()
	defer muLogt.Unlock()

	if logTraceFlags&Trfnbase > 0 {
		str = filepath.Base(endFn)
	} else {
		str = endFn
	}

	str = strMinWidth(str, logAlignFunc) + endMsg

	if logTraceFlags&Trnodur == 0 {
		str += " Dur:" + endTime.Sub(start).Round(time.Microsecond).String()
	}
	if logTraceFlags&Trendtime > 0 {
		str += formatTime(endTime, logTraceFlags&Trmicroseconds > 0, " Time:")
	}
	helplt(3+lvladj, trlabel+str, reffile, reflnum)
}

func helpltbeg(lvladj int, trlabel string, begMsg string) (begTime time.Time, begFn, reffile, reflnum string) {
	begTime = time.Now()
	begFn = Lvl(Lgpar + lvladj)
	if begMsg != "" {
		begMsg = " " + begMsg
	}
	var str string
	muLogt.Lock()
	defer muLogt.Unlock()

	if logTraceFlags&Trfnbase > 0 {
		str = filepath.Base(begFn)
	} else {
		str = begFn
	}

	str = strMinWidth(str, logAlignFunc) + begMsg

	if logTraceFlags&Trbegtime > 0 {
		str += formatTime(begTime, logTraceFlags&Trmicroseconds > 0, " Time:")
	}
	reffile, reflnum = helplt(3, trlabel+str, "", "")
	return begTime, begFn, reffile, reflnum
}

// LogTrace - log the begin tracing portion of the current function name
// [adjusting output according to the configuration settings such as Trace Flags,
// stdlib log, etc. at the time of its execution] and return a pairing end func
// that must be called within the same func.
//	Idiomatic usage at func start: defer fn.LogTrace()()
//  NOTE that the pairing return function uses the configurations that are at
//  its time of execution which [you] may have changed since the begin portion.
//  Also see LogCondTrace.
func LogTrace() func() {
	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func() {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceLab, "")
	return func() {
		helpltend(0, LendTraceLab, begTime, begFn, reffile, reflnum, "")
	}
}

// LogCondTrace - conditional version of LogTrace.
// cond - if true call LogTrace.
func LogCondTrace(cond bool) func() {
	if !cond {
		return func() {}
	}

	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func() {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceLab, "")
	return func() {
		helpltend(0, LendTraceLab, begTime, begFn, reffile, reflnum, "")
	}
}

// LogCondTraceMsgs - conditional version of LogTraceMsgs.
//	cond - if true call LogTraceMsgs.
func LogCondTraceMsgs(cond bool, begMsg string) func(endMsg string) {
	if !cond {
		return func(string) {}
	}

	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgsLab, begMsg)
	return func(endMsg string) {
		helpltend(0, LendTraceMsgsLab, begTime, begFn, reffile, reflnum, endMsg)
	}
}

// LogTraceMsgs - log the begin tracing portion of the current function name
// [adjusting output according to the configuration settings such as Trace Flags,
// stdlib log, etc. at the time of its execution] and return a pairing end func
// that must be called within the same func.
//	begMsg - printed after funcname when the LogTraceMsgs is invoked
//	endMsg - printed after funcname when the LogTraceMsgs returned func is invoked.
//	Idiomatic usage at func start: defer fn.LogTraceMsgs("begMsg")("endMsg")
//  NOTE that the pairing return function uses the configurations that are at
//  its time of execution which [you] may have changed since the begin portion.
//  Also see LogTraceMsgp, LogCondTraceMsgs, LogCondTraceMsgp.
func LogTraceMsgs(begMsg string) func(endMsg string) {
	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgsLab, begMsg)
	return func(endMsg string) {
		helpltend(0, LendTraceMsgsLab, begTime, begFn, reffile, reflnum, endMsg)
	}
}

// LogTraceMsgp - same as LogTraceMsgs however endMsg is a pointer to a string.
func LogTraceMsgp(begMsg string) func(endMsg *string) {
	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(*string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgpLab, begMsg)
	return func(endMsg *string) {
		helpltend(0, LendTraceMsgpLab, begTime, begFn, reffile, reflnum, *endMsg)
	}
}

// LogCondTraceMsgp - same as LogCondTraceMsgs however endMsg is a pointer to a string.
func LogCondTraceMsgp(cond bool, begMsg string) func(endMsg *string) {
	if !cond {
		return func(*string) {}
	}

	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(*string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgpLab, begMsg)
	return func(endMsg *string) {
		helpltend(0, LendTraceMsgpLab, begTime, begFn, reffile, reflnum, *endMsg)
	}
}
<commit_msg>LogCondMsg added<commit_after>// Copyright 2017 phcurtis fn Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fn

import (
	"errors"
	"fmt"
	"log"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

func strMinWidth(str string, width int) string {
	len1 := len(str)
	if len1 < width {
		str = str + strings.Repeat(" ", width-len1)
	}
	return str
}

// fn log trace but may first need to find appropriate filename and line num
func helplt(lvl int, msg, reffile, reflnum string) (newReffile, newReflnum string) {
	var filenlr string

	// get original [current] log flags
	orgflags := logt.Flags()
	sl := log.Lshortfile | log.Llongfile
	lfn := orgflags & sl

	var ref string

	// if log flags are including filename
	if lfn > 0 {
		_, file, line, _ := runtime.Caller(lvl)
		linenum := fmt.Sprintf(":%d", line)
		if orgflags&log.Lshortfile > 0 {
			file = filepath.Base(file)
		} else {
			// log.Llongfile
			if logTraceFlags&Trfilenogps > 0 {
				if strings.HasPrefix(file, gopathsrc) {
					file = file[len(gopathsrc):]
				}
			}
		}
		newReffile = filepath.Base(file)
		newReflnum = linenum

		// seems if this is true there is a problem elsewhere
		// as in a weird invocation end portion of log trace,
		// possible by passing that portion and invoking in
		// another function which package fn does NOT support.
		if reffile != "" && reffile != newReffile {
			logt.Panic(errors.New("reffile:" + reffile + " != newReffile:" + newReffile))
		}

		if reffile != "" && logTraceFlags&Trfnobegref == 0 {
			if logTraceFlags&Trfbegrefincfile > 0 {
				ref = "<" + reffile + reflnum + ">"
			} else {
				ref = "<" + reflnum + ">"
			}
		}

		filenlr = file + linenum + ref + " "
		filenlr = strMinWidth(filenlr, logAlignFile)

		// set log flags not to include filename
		logt.SetFlags(orgflags &^ sl)
	}
	logt.Printf("%s%s", filenlr, msg)
	if lfn > 0 {
		// restore log flags
		logt.SetFlags(orgflags)
	}
	return newReffile, newReflnum
}

func formatTime(t time.Time, microseconds bool, msg string) string {
	yr, mon, dy := t.Date()
	hr, min, sec := t.Clock()
	var micro string
	if microseconds {
		micro = fmt.Sprintf(".%06d", t.Nanosecond()/1e3)
	}
	return fmt.Sprintf("%s%d/%02d/%02d %02d:%02d:%02d%s", msg, yr, mon, dy, hr, min, sec, micro)
}

func helpltend(lvladj int, trlabel string, start time.Time, begFn, reffile, reflnum, endMsg string) {
	endTime := time.Now()
	endFn := Lvl(Lgpar + lvladj)
	if begFn != endFn {
		if strings.Contains(CStk(), "<--runtime.gopanic") {
			logt.Println("GOPANIC DETECTED --exiting '"+trlabel+"'(helpltend)>CStk:", CStk())
			logt.Println("begFn:"+begFn+" != endFn:"+endFn, " reffile:", reffile, " reflnum", reflnum, "\n\n ")
			return
		}
		// if Idiomatic usage of LogTrace and LogTraceMsgs then should not have a panic.
		err := fmt.Sprintf("begFn != endFn\n begFn:%s\n endFn:%s\n  Cstk:%s \n"+
			"Panic probable cause due to end trace pairing return portion called from different func",
			begFn, endFn, CStk())
		logt.Panic(errors.New(err)) // see todo above
	}
	if endMsg != "" {
		endMsg = " " + endMsg
	}
	var str string

	muLogt.Lock()
	defer muLogt.Unlock()

	if logTraceFlags&Trfnbase > 0 {
		str = filepath.Base(endFn)
	} else {
		str = endFn
	}

	str = strMinWidth(str, logAlignFunc) + endMsg

	if logTraceFlags&Trnodur == 0 {
		str += " Dur:" + endTime.Sub(start).Round(time.Microsecond).String()
	}
	if logTraceFlags&Trendtime > 0 {
		str += formatTime(endTime, logTraceFlags&Trmicroseconds > 0, " Time:")
	}
	helplt(3+lvladj, trlabel+str, reffile, reflnum)
}

func helpltbeg(lvladj int, trlabel string, begMsg string) (begTime time.Time, begFn, reffile, reflnum string) {
	begTime = time.Now()
	begFn = Lvl(Lgpar + lvladj)
	if begMsg != "" {
		begMsg = " " + begMsg
	}
	var str string
	muLogt.Lock()
	defer muLogt.Unlock()

	if logTraceFlags&Trfnbase > 0 {
		str = filepath.Base(begFn)
	} else {
		str = begFn
	}

	str = strMinWidth(str, logAlignFunc) + begMsg

	if logTraceFlags&Trbegtime > 0 {
		str += formatTime(begTime, logTraceFlags&Trmicroseconds > 0, " Time:")
	}
	reffile, reflnum = helplt(3, trlabel+str, "", "")
	return begTime, begFn, reffile, reflnum
}

// LogTrace - log the begin tracing portion of the current function name
// [adjusting output according to the configuration settings such as Trace Flags,
// stdlib log, etc. at the time of its execution] and return a pairing end func
// that must be called within the same func.
//	Idiomatic usage at func start: defer fn.LogTrace()()
//  NOTE that the pairing return function uses the configurations that are at
//  its time of execution which [you] may have changed since the begin portion.
//  Also see LogCondTrace.
func LogTrace() func() {
	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func() {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceLab, "")
	return func() {
		helpltend(0, LendTraceLab, begTime, begFn, reffile, reflnum, "")
	}
}

// LogCondTrace - conditional version of LogTrace.
// cond - if true call LogTrace.
func LogCondTrace(cond bool) func() {
	if !cond {
		return func() {}
	}

	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func() {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceLab, "")
	return func() {
		helpltend(0, LendTraceLab, begTime, begFn, reffile, reflnum, "")
	}
}

// LogCondMsg - logs message if cond true.
func LogCondMsg(cond bool, msg string) {
	if !cond {
		return
	}

	muLogt.Lock()
	// may not want this check
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return
	}
	muLogt.Unlock()

	helpltbeg(0, "Msg:", msg)
}

// LogCondTraceMsgs - conditional version of LogTraceMsgs.
//	cond - if true call LogTraceMsgs.
func LogCondTraceMsgs(cond bool, begMsg string) func(endMsg string) {
	if !cond {
		return func(string) {}
	}

	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgsLab, begMsg)
	return func(endMsg string) {
		helpltend(0, LendTraceMsgsLab, begTime, begFn, reffile, reflnum, endMsg)
	}
}

// LogTraceMsgs - log the begin tracing portion of the current function name
// [adjusting output according to the configuration settings such as Trace Flags,
// stdlib log, etc. at the time of its execution] and return a pairing end func
// that must be called within the same func.
//	begMsg - printed after funcname when the LogTraceMsgs is invoked
//	endMsg - printed after funcname when the LogTraceMsgs returned func is invoked.
//	Idiomatic usage at func start: defer fn.LogTraceMsgs("begMsg")("endMsg")
//  NOTE that the pairing return function uses the configurations that are at
//  its time of execution which [you] may have changed since the begin portion.
//  Also see LogTraceMsgp, LogCondTraceMsgs, LogCondTraceMsgp.
func LogTraceMsgs(begMsg string) func(endMsg string) {
	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgsLab, begMsg)
	return func(endMsg string) {
		helpltend(0, LendTraceMsgsLab, begTime, begFn, reffile, reflnum, endMsg)
	}
}

// LogTraceMsgp - same as LogTraceMsgs however endMsg is a pointer to a string.
func LogTraceMsgp(begMsg string) func(endMsg *string) {
	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(*string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgpLab, begMsg)
	return func(endMsg *string) {
		helpltend(0, LendTraceMsgpLab, begTime, begFn, reffile, reflnum, *endMsg)
	}
}

// LogCondTraceMsgp - same as LogCondTraceMsgs however endMsg is a pointer to a string.
func LogCondTraceMsgp(cond bool, begMsg string) func(endMsg *string) {
	if !cond {
		return func(*string) {}
	}

	muLogt.Lock()
	if logTraceFlags&Trlogignore > 0 {
		muLogt.Unlock()
		return func(*string) {}
	}
	muLogt.Unlock()

	begTime, begFn, reffile, reflnum := helpltbeg(0, LbegTraceMsgpLab, begMsg)
	return func(endMsg *string) {
		helpltend(0, LendTraceMsgpLab, begTime, begFn, reffile, reflnum, *endMsg)
	}
}
<|endoftext|>


<commit_before>// +build !windows

package termios

import (
	"fmt"
	"os"

	"golang.org/x/sys/unix"
)

func open_device(path string) (uintptr, error) {
	fd, err := unix.Open(path, unix.O_NOCTTY|unix.O_RDWR|unix.O_CLOEXEC, 0666)
	if err != nil {
		return 0, fmt.Errorf("unable to open %q: %v", path, err)
	}
	return uintptr(fd), nil
}

// Pty returns a UNIX 98 pseudoterminal device.
// Pty returns a pair of fds representing the master and slave pair.
func Pty() (*os.File, *os.File, error) {
	ptm, err := open_pty_master()
	if err != nil {
		return nil, nil, err
	}

	sname, err := Ptsname(ptm)
	if err != nil {
		return nil, nil, err
	}

	err = grantpt(ptm)
	if err != nil {
		return nil, nil, err
	}

	err = unlockpt(ptm)
	if err != nil {
		return nil, nil, err
	}

	pts, err := open_device(sname)
	if err != nil {
		return nil, nil, err
	}
	return os.NewFile(uintptr(ptm), "ptm"), os.NewFile(uintptr(pts), sname), nil
}
<commit_msg>Avoid leaking ptm fd in case of an error<commit_after>// +build !windows

package termios

import (
	"fmt"
	"os"

	"golang.org/x/sys/unix"
)

func open_device(path string) (uintptr, error) {
	fd, err := unix.Open(path, unix.O_NOCTTY|unix.O_RDWR|unix.O_CLOEXEC, 0666)
	if err != nil {
		return 0, fmt.Errorf("unable to open %q: %v", path, err)
	}
	return uintptr(fd), nil
}

// Pty returns a UNIX 98 pseudoterminal device.
// Pty returns a pair of fds representing the master and slave pair.
func Pty() (*os.File, *os.File, error) {
	ptm, err := open_pty_master()
	if err != nil {
		return nil, nil, err
	}

	sname, err := Ptsname(ptm)
	if err != nil {
		unix.Close(int(ptm))
		return nil, nil, err
	}

	err = grantpt(ptm)
	if err != nil {
		unix.Close(int(ptm))
		return nil, nil, err
	}

	err = unlockpt(ptm)
	if err != nil {
		unix.Close(int(ptm))
		return nil, nil, err
	}

	pts, err := open_device(sname)
	if err != nil {
		unix.Close(int(ptm))
		return nil, nil, err
	}
	return os.NewFile(uintptr(ptm), "ptm"), os.NewFile(uintptr(pts), sname), nil
}
<|endoftext|>


<commit_before>package geo_skeleton

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {
	self.DB = skeleton.Database{File: string(self.getFile())}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, string(self.getTable()))
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return self.File
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return self.Table
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) (error) {
	err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {
	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<commit_msg>fixed geots<commit_after>package geo_skeleton

import "fmt"

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {

	fmt.Println("[GEOTS]", string(self.getFile()), string(self.getTable()))

	self.DB = skeleton.Database{File: string(self.getFile())}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, string(self.getTable()))
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return self.File
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return self.Table
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) (error) {
	err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {
	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<|endoftext|>


<commit_before>// errorcheck

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

// Test that incorrect uses of the blank identifer are caught.
// Does not compile.

package _	// ERROR "invalid package name _"

var t struct {
	_ int
}

type T struct {
      _ []int
}

func main() {
	_()	// ERROR "cannot use _ as value"
	x := _+1	// ERROR "cannot use _ as value"
	_ = x
	_ = t._ // ERROR "cannot refer to blank field"

      var v1, v2 T
      _ = v1 == v2 // ERROR "cannot be compared|non-comparable"
}
<commit_msg>test: match gccgo error messages for blank1.go<commit_after>// errorcheck

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

// Test that incorrect uses of the blank identifer are caught.
// Does not compile.

package _	// ERROR "invalid package name _"

var t struct {
	_ int
}

type T struct {
      _ []int
}

func main() {
	_()	// ERROR "cannot use _ as value"
	x := _+1	// ERROR "cannot use _ as value"
	_ = x
	_ = t._ // ERROR "cannot refer to blank field|invalid use of"

      var v1, v2 T
      _ = v1 == v2 // ERROR "cannot be compared|non-comparable"
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"io"

	"github.com/docker/cli/cli/command"
	"github.com/docker/cli/cli/command/stack/options"
	composetypes "github.com/docker/cli/cli/compose/types"
	"github.com/morikuni/aec"
	"github.com/pkg/errors"
)

// RunDeploy is the kubernetes implementation of docker stack deploy
func RunDeploy(dockerCli *KubeCli, opts options.Deploy, cfg *composetypes.Config) error {
	cmdOut := dockerCli.Out()
	// Check arguments
	if len(opts.Composefiles) == 0 {
		return errors.Errorf("Please specify only one compose file (with --compose-file).")
	}

	// Initialize clients
	composeClient, err := dockerCli.composeClient()
	if err != nil {
		return err
	}
	stacks, err := composeClient.Stacks(false)
	if err != nil {
		return err
	}

	stack, err := stacks.FromCompose(dockerCli.Err(), opts.Namespace, cfg)
	if err != nil {
		return err
	}

	configMaps := composeClient.ConfigMaps()
	secrets := composeClient.Secrets()
	services := composeClient.Services()

	if err := stacks.IsColliding(services, stack); err != nil {
		return err
	}

	if err := stack.createFileBasedConfigMaps(configMaps); err != nil {
		return err
	}

	if err := stack.createFileBasedSecrets(secrets); err != nil {
		return err
	}

	if err = stacks.CreateOrUpdate(stack); err != nil {
		return err
	}

	fmt.Fprintln(cmdOut, "Waiting for the stack to be stable and running...")
	v1beta1Cli, err := dockerCli.stacksv1beta1()
	if err != nil {
		return err
	}

	pods := composeClient.Pods()
	watcher := &deployWatcher{
		stacks: v1beta1Cli,
		pods:   pods,
	}
	statusUpdates := make(chan serviceStatus)
	displayDone := make(chan struct{})
	go func() {
		defer close(displayDone)
		display := newStatusDisplay(dockerCli.Out())
		for status := range statusUpdates {
			display.OnStatus(status)
		}
	}()

	err = watcher.Watch(stack.Name, stack.getServices(), statusUpdates)
	close(statusUpdates)
	<-displayDone
	if err != nil {
		return err
	}
	fmt.Fprintf(cmdOut, "\nStack %s is stable and running\n\n", stack.Name)
	return nil

}

type statusDisplay interface {
	OnStatus(serviceStatus)
}
type metaServiceState string

const (
	metaServiceStateReady   = metaServiceState("Ready")
	metaServiceStatePending = metaServiceState("Pending")
	metaServiceStateFailed  = metaServiceState("Failed")
)

func metaStateFromStatus(status serviceStatus) metaServiceState {
	switch {
	case status.podsReady > 0:
		return metaServiceStateReady
	case status.podsPending > 0:
		return metaServiceStatePending
	default:
		return metaServiceStateFailed
	}
}

type forwardOnlyStatusDisplay struct {
	o      *command.OutStream
	states map[string]metaServiceState
}

func (d *forwardOnlyStatusDisplay) OnStatus(status serviceStatus) {
	state := metaStateFromStatus(status)
	if d.states[status.name] != state {
		d.states[status.name] = state
		fmt.Fprintf(d.o, "%s: %s\n", status.name, state)
	}
}

type interactiveStatusDisplay struct {
	o        *command.OutStream
	statuses []serviceStatus
}

func (d *interactiveStatusDisplay) OnStatus(status serviceStatus) {
	b := aec.EmptyBuilder
	for ix := 0; ix < len(d.statuses); ix++ {
		b = b.Up(1).EraseLine(aec.EraseModes.All)
	}
	b = b.Column(0)
	fmt.Fprint(d.o, b.ANSI)
	updated := false
	for ix, s := range d.statuses {
		if s.name == status.name {
			d.statuses[ix] = status
			s = status
			updated = true
		}
		displayInteractiveServiceStatus(s, d.o)
	}
	if !updated {
		d.statuses = append(d.statuses, status)
		displayInteractiveServiceStatus(status, d.o)
	}
}

func displayInteractiveServiceStatus(status serviceStatus, o io.Writer) {
	state := metaStateFromStatus(status)
	totalFailed := status.podsFailed + status.podsSucceeded + status.podsUnknown
	fmt.Fprintf(o, "%[1]s: %[2]s\t\t[pod status: %[3]d/%[6]d ready, %[4]d/%[6]d pending, %[5]d/%[6]d failed]\n", status.name, state,
		status.podsReady, status.podsPending, totalFailed, status.podsTotal)
}

func newStatusDisplay(o *command.OutStream) statusDisplay {
	if !o.IsTerminal() {
		return &forwardOnlyStatusDisplay{o: o, states: map[string]metaServiceState{}}
	}
	return &interactiveStatusDisplay{o: o}
}
<commit_msg>Remove composefiles lenght check on k8s RunDeploy..<commit_after>package kubernetes

import (
	"fmt"
	"io"

	"github.com/docker/cli/cli/command"
	"github.com/docker/cli/cli/command/stack/options"
	composetypes "github.com/docker/cli/cli/compose/types"
	"github.com/morikuni/aec"
)

// RunDeploy is the kubernetes implementation of docker stack deploy
func RunDeploy(dockerCli *KubeCli, opts options.Deploy, cfg *composetypes.Config) error {
	cmdOut := dockerCli.Out()

	// Initialize clients
	composeClient, err := dockerCli.composeClient()
	if err != nil {
		return err
	}
	stacks, err := composeClient.Stacks(false)
	if err != nil {
		return err
	}

	stack, err := stacks.FromCompose(dockerCli.Err(), opts.Namespace, cfg)
	if err != nil {
		return err
	}

	configMaps := composeClient.ConfigMaps()
	secrets := composeClient.Secrets()
	services := composeClient.Services()

	if err := stacks.IsColliding(services, stack); err != nil {
		return err
	}

	if err := stack.createFileBasedConfigMaps(configMaps); err != nil {
		return err
	}

	if err := stack.createFileBasedSecrets(secrets); err != nil {
		return err
	}

	if err = stacks.CreateOrUpdate(stack); err != nil {
		return err
	}

	fmt.Fprintln(cmdOut, "Waiting for the stack to be stable and running...")
	v1beta1Cli, err := dockerCli.stacksv1beta1()
	if err != nil {
		return err
	}

	pods := composeClient.Pods()
	watcher := &deployWatcher{
		stacks: v1beta1Cli,
		pods:   pods,
	}
	statusUpdates := make(chan serviceStatus)
	displayDone := make(chan struct{})
	go func() {
		defer close(displayDone)
		display := newStatusDisplay(dockerCli.Out())
		for status := range statusUpdates {
			display.OnStatus(status)
		}
	}()

	err = watcher.Watch(stack.Name, stack.getServices(), statusUpdates)
	close(statusUpdates)
	<-displayDone
	if err != nil {
		return err
	}
	fmt.Fprintf(cmdOut, "\nStack %s is stable and running\n\n", stack.Name)
	return nil

}

type statusDisplay interface {
	OnStatus(serviceStatus)
}
type metaServiceState string

const (
	metaServiceStateReady   = metaServiceState("Ready")
	metaServiceStatePending = metaServiceState("Pending")
	metaServiceStateFailed  = metaServiceState("Failed")
)

func metaStateFromStatus(status serviceStatus) metaServiceState {
	switch {
	case status.podsReady > 0:
		return metaServiceStateReady
	case status.podsPending > 0:
		return metaServiceStatePending
	default:
		return metaServiceStateFailed
	}
}

type forwardOnlyStatusDisplay struct {
	o      *command.OutStream
	states map[string]metaServiceState
}

func (d *forwardOnlyStatusDisplay) OnStatus(status serviceStatus) {
	state := metaStateFromStatus(status)
	if d.states[status.name] != state {
		d.states[status.name] = state
		fmt.Fprintf(d.o, "%s: %s\n", status.name, state)
	}
}

type interactiveStatusDisplay struct {
	o        *command.OutStream
	statuses []serviceStatus
}

func (d *interactiveStatusDisplay) OnStatus(status serviceStatus) {
	b := aec.EmptyBuilder
	for ix := 0; ix < len(d.statuses); ix++ {
		b = b.Up(1).EraseLine(aec.EraseModes.All)
	}
	b = b.Column(0)
	fmt.Fprint(d.o, b.ANSI)
	updated := false
	for ix, s := range d.statuses {
		if s.name == status.name {
			d.statuses[ix] = status
			s = status
			updated = true
		}
		displayInteractiveServiceStatus(s, d.o)
	}
	if !updated {
		d.statuses = append(d.statuses, status)
		displayInteractiveServiceStatus(status, d.o)
	}
}

func displayInteractiveServiceStatus(status serviceStatus, o io.Writer) {
	state := metaStateFromStatus(status)
	totalFailed := status.podsFailed + status.podsSucceeded + status.podsUnknown
	fmt.Fprintf(o, "%[1]s: %[2]s\t\t[pod status: %[3]d/%[6]d ready, %[4]d/%[6]d pending, %[5]d/%[6]d failed]\n", status.name, state,
		status.podsReady, status.podsPending, totalFailed, status.podsTotal)
}

func newStatusDisplay(o *command.OutStream) statusDisplay {
	if !o.IsTerminal() {
		return &forwardOnlyStatusDisplay{o: o, states: map[string]metaServiceState{}}
	}
	return &interactiveStatusDisplay{o: o}
}
<|endoftext|>


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

// Package list implements a doubly linked list.
//
// To iterate over a list (where l is a *List):
//	for e := l.Front(); e != nil; e = e.Next() {
//		// do something with e.Value
//	}
//
package list

// Element is an element of a linked list.
type Element struct {
	// Next and previous pointers in the doubly-linked list of elements.
	// To simplify the implementation, internally a list l is implemented
	// as a ring, such that &l.root is both the next element of the last
	// list element (l.Back()) and the previous element of the first list
	// element (l.Front()).
	next, prev *Element

	// The list to which this element belongs.
	list *List

	// The value stored with this element.
	Value interface{}
}

// Next returns the next list element or nil.
func (e *Element) Next() *Element {
	if p := e.next; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
	if p := e.prev; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
	root Element // sentinel list element, only &root, root.prev, and root.next are used
	len  int     // current list length excluding (this) sentinel element
}

// Init initializes or clears list l.
func (l *List) Init() *List {
	l.root.next = &l.root
	l.root.prev = &l.root
	l.len = 0
	return l
}

// New returns an initialized list.
func New() *List { return new(List).Init() }

// Len returns the number of elements of list l.
// The complexity is O(1).
func (l *List) Len() int { return l.len }

// Front returns the first element of list l or nil
func (l *List) Front() *Element {
	if l.len == 0 {
		return nil
	}
	return l.root.next
}

// Back returns the last element of list l or nil.
func (l *List) Back() *Element {
	if l.len == 0 {
		return nil
	}
	return l.root.prev
}

// lazyInit lazily initializes a zero List value.
func (l *List) lazyInit() {
	if l.root.next == nil {
		l.Init()
	}
}

// insert inserts e after at, increments l.len, and returns e.
func (l *List) insert(e, at *Element) *Element {
	n := at.next
	at.next = e
	e.prev = at
	e.next = n
	n.prev = e
	e.list = l
	l.len++
	return e
}

// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
func (l *List) insertValue(v interface{}, at *Element) *Element {
	return l.insert(&Element{Value: v}, at)
}

// remove removes e from its list, decrements l.len, and returns e.
func (l *List) remove(e *Element) *Element {
	e.prev.next = e.next
	e.next.prev = e.prev
	e.next = nil // avoid memory leaks
	e.prev = nil // avoid memory leaks
	e.list = nil
	l.len--
	return e
}

// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
func (l *List) Remove(e *Element) interface{} {
	if e.list == l {
		// if e.list == l, l must have been initialized when e was inserted
		// in l or l == nil (e is a zero Element) and l.remove will crash
		l.remove(e)
	}
	return e.Value
}

// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *List) PushFront(v interface{}) *Element {
	l.lazyInit()
	return l.insertValue(v, &l.root)
}

// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *List) PushBack(v interface{}) *Element {
	l.lazyInit()
	return l.insertValue(v, l.root.prev)
}

// InsertBefore inserts a new element e with value v immediately before mark and returns e.
// If mark is not an element of l, the list is not modified.
func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
	if mark.list != l {
		return nil
	}
	// see comment in List.Remove about initialization of l
	return l.insertValue(v, mark.prev)
}

// InsertAfter inserts a new element e with value v immediately after mark and returns e.
// If mark is not an element of l, the list is not modified.
func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
	if mark.list != l {
		return nil
	}
	// see comment in List.Remove about initialization of l
	return l.insertValue(v, mark)
}

// MoveToFront moves element e to the front of list l.
// If e is not an element of l, the list is not modified.
func (l *List) MoveToFront(e *Element) {
	if e.list != l || l.root.next == e {
		return
	}
	// see comment in List.Remove about initialization of l
	l.insert(l.remove(e), &l.root)
}

// MoveToBack moves element e to the back of list l.
// If e is not an element of l, the list is not modified.
func (l *List) MoveToBack(e *Element) {
	if e.list != l || l.root.prev == e {
		return
	}
	// see comment in List.Remove about initialization of l
	l.insert(l.remove(e), l.root.prev)
}

// MoveBefore moves element e to its new position before mark.
// If e is not an element of l, or e == mark, the list is not modified.
func (l *List) MoveBefore(e, mark *Element) {
	if e.list != l || e == mark {
		return
	}
	l.insert(l.remove(e), mark.prev)
}

// MoveAfter moves element e to its new position after mark.
// If e is not an element of l, or e == mark, the list is not modified.
func (l *List) MoveAfter(e, mark *Element) {
	if e.list != l || e == mark {
		return
	}
	l.insert(l.remove(e), mark)
}

// PushBackList inserts a copy of an other list at the back of list l.
// The lists l and other may be the same.
func (l *List) PushBackList(other *List) {
	l.lazyInit()
	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
		l.insertValue(e.Value, l.root.prev)
	}
}

// PushFrontList inserts a copy of an other list at the front of list l.
// The lists l and other may be the same.
func (l *List) PushFrontList(other *List) {
	l.lazyInit()
	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
		l.insertValue(e.Value, &l.root)
	}
}
<commit_msg>container/list: Add missing period to doc comment for Front<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package list implements a doubly linked list.
//
// To iterate over a list (where l is a *List):
//	for e := l.Front(); e != nil; e = e.Next() {
//		// do something with e.Value
//	}
//
package list

// Element is an element of a linked list.
type Element struct {
	// Next and previous pointers in the doubly-linked list of elements.
	// To simplify the implementation, internally a list l is implemented
	// as a ring, such that &l.root is both the next element of the last
	// list element (l.Back()) and the previous element of the first list
	// element (l.Front()).
	next, prev *Element

	// The list to which this element belongs.
	list *List

	// The value stored with this element.
	Value interface{}
}

// Next returns the next list element or nil.
func (e *Element) Next() *Element {
	if p := e.next; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
	if p := e.prev; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
	root Element // sentinel list element, only &root, root.prev, and root.next are used
	len  int     // current list length excluding (this) sentinel element
}

// Init initializes or clears list l.
func (l *List) Init() *List {
	l.root.next = &l.root
	l.root.prev = &l.root
	l.len = 0
	return l
}

// New returns an initialized list.
func New() *List { return new(List).Init() }

// Len returns the number of elements of list l.
// The complexity is O(1).
func (l *List) Len() int { return l.len }

// Front returns the first element of list l or nil.
func (l *List) Front() *Element {
	if l.len == 0 {
		return nil
	}
	return l.root.next
}

// Back returns the last element of list l or nil.
func (l *List) Back() *Element {
	if l.len == 0 {
		return nil
	}
	return l.root.prev
}

// lazyInit lazily initializes a zero List value.
func (l *List) lazyInit() {
	if l.root.next == nil {
		l.Init()
	}
}

// insert inserts e after at, increments l.len, and returns e.
func (l *List) insert(e, at *Element) *Element {
	n := at.next
	at.next = e
	e.prev = at
	e.next = n
	n.prev = e
	e.list = l
	l.len++
	return e
}

// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
func (l *List) insertValue(v interface{}, at *Element) *Element {
	return l.insert(&Element{Value: v}, at)
}

// remove removes e from its list, decrements l.len, and returns e.
func (l *List) remove(e *Element) *Element {
	e.prev.next = e.next
	e.next.prev = e.prev
	e.next = nil // avoid memory leaks
	e.prev = nil // avoid memory leaks
	e.list = nil
	l.len--
	return e
}

// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
func (l *List) Remove(e *Element) interface{} {
	if e.list == l {
		// if e.list == l, l must have been initialized when e was inserted
		// in l or l == nil (e is a zero Element) and l.remove will crash
		l.remove(e)
	}
	return e.Value
}

// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *List) PushFront(v interface{}) *Element {
	l.lazyInit()
	return l.insertValue(v, &l.root)
}

// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *List) PushBack(v interface{}) *Element {
	l.lazyInit()
	return l.insertValue(v, l.root.prev)
}

// InsertBefore inserts a new element e with value v immediately before mark and returns e.
// If mark is not an element of l, the list is not modified.
func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
	if mark.list != l {
		return nil
	}
	// see comment in List.Remove about initialization of l
	return l.insertValue(v, mark.prev)
}

// InsertAfter inserts a new element e with value v immediately after mark and returns e.
// If mark is not an element of l, the list is not modified.
func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
	if mark.list != l {
		return nil
	}
	// see comment in List.Remove about initialization of l
	return l.insertValue(v, mark)
}

// MoveToFront moves element e to the front of list l.
// If e is not an element of l, the list is not modified.
func (l *List) MoveToFront(e *Element) {
	if e.list != l || l.root.next == e {
		return
	}
	// see comment in List.Remove about initialization of l
	l.insert(l.remove(e), &l.root)
}

// MoveToBack moves element e to the back of list l.
// If e is not an element of l, the list is not modified.
func (l *List) MoveToBack(e *Element) {
	if e.list != l || l.root.prev == e {
		return
	}
	// see comment in List.Remove about initialization of l
	l.insert(l.remove(e), l.root.prev)
}

// MoveBefore moves element e to its new position before mark.
// If e is not an element of l, or e == mark, the list is not modified.
func (l *List) MoveBefore(e, mark *Element) {
	if e.list != l || e == mark {
		return
	}
	l.insert(l.remove(e), mark.prev)
}

// MoveAfter moves element e to its new position after mark.
// If e is not an element of l, or e == mark, the list is not modified.
func (l *List) MoveAfter(e, mark *Element) {
	if e.list != l || e == mark {
		return
	}
	l.insert(l.remove(e), mark)
}

// PushBackList inserts a copy of an other list at the back of list l.
// The lists l and other may be the same.
func (l *List) PushBackList(other *List) {
	l.lazyInit()
	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
		l.insertValue(e.Value, l.root.prev)
	}
}

// PushFrontList inserts a copy of an other list at the front of list l.
// The lists l and other may be the same.
func (l *List) PushFrontList(other *List) {
	l.lazyInit()
	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
		l.insertValue(e.Value, &l.root)
	}
}
<|endoftext|>


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

// This file implements API tests across platforms and will never have a build
// tag.

package net

import (
	"os"
	"runtime"
	"strings"
	"testing"
	"time"
)

func strfunc(s string) func() string {
	return func() string {
		return s
	}
}

func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) {
	switch net {
	case "udp":
		return []byte("UDP PACKETCONN TEST"), nil
	case "ip":
		if skip, skipmsg := skipRawSocketTest(t); skip {
			return nil, func() {
				t.Logf(skipmsg)
			}
		}
		b, err := (&icmpMessage{
			Type: icmpv4EchoRequest, Code: 0,
			Body: &icmpEcho{
				ID: os.Getpid() & 0xffff, Seq: i + 1,
				Data: []byte("IP PACKETCONN TEST"),
			},
		}).Marshal()
		if err != nil {
			return nil, func() {
				t.Fatalf("icmpMessage.Marshal failed: %v", err)
			}
		}
		return b, nil
	case "unixgram":
		switch runtime.GOOS {
		case "plan9", "windows":
			return nil, func() {
				t.Logf("skipping %q test on %q", net, runtime.GOOS)
			}
		default:
			return []byte("UNIXGRAM PACKETCONN TEST"), nil
		}
	default:
		return nil, func() {
			t.Logf("skipping %q test", net)
		}
	}
}

var packetConnTests = []struct {
	net   string
	addr1 func() string
	addr2 func() string
}{
	{"udp", strfunc("127.0.0.1:0"), strfunc("127.0.0.1:0")},
	{"ip:icmp", strfunc("127.0.0.1"), strfunc("127.0.0.1")},
	{"unixgram", testUnixAddr, testUnixAddr},
}

func TestPacketConn(t *testing.T) {
	closer := func(c PacketConn, net, addr1, addr2 string) {
		c.Close()
		switch net {
		case "unixgram":
			os.Remove(addr1)
			os.Remove(addr2)
		}
	}

	for i, tt := range packetConnTests {
		netstr := strings.Split(tt.net, ":")
		wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
		if skipOrFatalFn != nil {
			skipOrFatalFn()
			continue
		}

		addr1, addr2 := tt.addr1(), tt.addr2()
		c1, err := ListenPacket(tt.net, addr1)
		if err != nil {
			t.Fatalf("ListenPacket failed: %v", err)
		}
		defer closer(c1, netstr[0], addr1, addr2)
		c1.LocalAddr()
		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		c2, err := ListenPacket(tt.net, addr2)
		if err != nil {
			t.Fatalf("ListenPacket failed: %v", err)
		}
		defer closer(c2, netstr[0], addr1, addr2)
		c2.LocalAddr()
		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil {
			t.Fatalf("PacketConn.WriteTo failed: %v", err)
		}
		rb2 := make([]byte, 128)
		if _, _, err := c2.ReadFrom(rb2); err != nil {
			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
		}
		if _, err := c2.WriteTo(wb, c1.LocalAddr()); err != nil {
			t.Fatalf("PacketConn.WriteTo failed: %v", err)
		}
		rb1 := make([]byte, 128)
		if _, _, err := c1.ReadFrom(rb1); err != nil {
			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
		}
	}
}

func TestConnAndPacketConn(t *testing.T) {
	closer := func(c PacketConn, net, addr1, addr2 string) {
		c.Close()
		switch net {
		case "unixgram":
			os.Remove(addr1)
			os.Remove(addr2)
		}
	}

	for i, tt := range packetConnTests {
		var wb []byte
		netstr := strings.Split(tt.net, ":")
		wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
		if skipOrFatalFn != nil {
			skipOrFatalFn()
			continue
		}

		addr1, addr2 := tt.addr1(), tt.addr2()
		c1, err := ListenPacket(tt.net, addr1)
		if err != nil {
			t.Fatalf("ListenPacket failed: %v", err)
		}
		defer closer(c1, netstr[0], addr1, addr2)
		c1.LocalAddr()
		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		c2, err := Dial(tt.net, c1.LocalAddr().String())
		if err != nil {
			t.Fatalf("Dial failed: %v", err)
		}
		defer c2.Close()
		c2.LocalAddr()
		c2.RemoteAddr()
		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		if _, err := c2.Write(wb); err != nil {
			t.Fatalf("Conn.Write failed: %v", err)
		}
		rb1 := make([]byte, 128)
		if _, _, err := c1.ReadFrom(rb1); err != nil {
			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
		}
		var dst Addr
		switch netstr[0] {
		case "ip":
			dst = &IPAddr{IP: IPv4(127, 0, 0, 1)}
		case "unixgram":
			continue
		default:
			dst = c2.LocalAddr()
		}
		if _, err := c1.WriteTo(wb, dst); err != nil {
			t.Fatalf("PacketConn.WriteTo failed: %v", err)
		}
		rb2 := make([]byte, 128)
		if _, err := c2.Read(rb2); err != nil {
			t.Fatalf("Conn.Read failed: %v", err)
		}
	}
}
<commit_msg>net: drop unnecessary indirection from PacketConn tests<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements API tests across platforms and will never have a build
// tag.

package net

import (
	"os"
	"runtime"
	"strings"
	"testing"
	"time"
)

func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) {
	switch net {
	case "udp":
		return []byte("UDP PACKETCONN TEST"), nil
	case "ip":
		if skip, skipmsg := skipRawSocketTest(t); skip {
			return nil, func() {
				t.Logf(skipmsg)
			}
		}
		b, err := (&icmpMessage{
			Type: icmpv4EchoRequest, Code: 0,
			Body: &icmpEcho{
				ID: os.Getpid() & 0xffff, Seq: i + 1,
				Data: []byte("IP PACKETCONN TEST"),
			},
		}).Marshal()
		if err != nil {
			return nil, func() {
				t.Fatalf("icmpMessage.Marshal failed: %v", err)
			}
		}
		return b, nil
	case "unixgram":
		switch runtime.GOOS {
		case "plan9", "windows":
			return nil, func() {
				t.Logf("skipping %q test on %q", net, runtime.GOOS)
			}
		default:
			return []byte("UNIXGRAM PACKETCONN TEST"), nil
		}
	default:
		return nil, func() {
			t.Logf("skipping %q test", net)
		}
	}
}

var packetConnTests = []struct {
	net   string
	addr1 string
	addr2 string
}{
	{"udp", "127.0.0.1:0", "127.0.0.1:0"},
	{"ip:icmp", "127.0.0.1", "127.0.0.1"},
	{"unixgram", testUnixAddr(), testUnixAddr()},
}

func TestPacketConn(t *testing.T) {
	closer := func(c PacketConn, net, addr1, addr2 string) {
		c.Close()
		switch net {
		case "unixgram":
			os.Remove(addr1)
			os.Remove(addr2)
		}
	}

	for i, tt := range packetConnTests {
		netstr := strings.Split(tt.net, ":")
		wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
		if skipOrFatalFn != nil {
			skipOrFatalFn()
			continue
		}

		c1, err := ListenPacket(tt.net, tt.addr1)
		if err != nil {
			t.Fatalf("ListenPacket failed: %v", err)
		}
		defer closer(c1, netstr[0], tt.addr1, tt.addr2)
		c1.LocalAddr()
		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		c2, err := ListenPacket(tt.net, tt.addr2)
		if err != nil {
			t.Fatalf("ListenPacket failed: %v", err)
		}
		defer closer(c2, netstr[0], tt.addr1, tt.addr2)
		c2.LocalAddr()
		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil {
			t.Fatalf("PacketConn.WriteTo failed: %v", err)
		}
		rb2 := make([]byte, 128)
		if _, _, err := c2.ReadFrom(rb2); err != nil {
			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
		}
		if _, err := c2.WriteTo(wb, c1.LocalAddr()); err != nil {
			t.Fatalf("PacketConn.WriteTo failed: %v", err)
		}
		rb1 := make([]byte, 128)
		if _, _, err := c1.ReadFrom(rb1); err != nil {
			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
		}
	}
}

func TestConnAndPacketConn(t *testing.T) {
	closer := func(c PacketConn, net, addr1, addr2 string) {
		c.Close()
		switch net {
		case "unixgram":
			os.Remove(addr1)
			os.Remove(addr2)
		}
	}

	for i, tt := range packetConnTests {
		var wb []byte
		netstr := strings.Split(tt.net, ":")
		wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
		if skipOrFatalFn != nil {
			skipOrFatalFn()
			continue
		}

		c1, err := ListenPacket(tt.net, tt.addr1)
		if err != nil {
			t.Fatalf("ListenPacket failed: %v", err)
		}
		defer closer(c1, netstr[0], tt.addr1, tt.addr2)
		c1.LocalAddr()
		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		c2, err := Dial(tt.net, c1.LocalAddr().String())
		if err != nil {
			t.Fatalf("Dial failed: %v", err)
		}
		defer c2.Close()
		c2.LocalAddr()
		c2.RemoteAddr()
		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))

		if _, err := c2.Write(wb); err != nil {
			t.Fatalf("Conn.Write failed: %v", err)
		}
		rb1 := make([]byte, 128)
		if _, _, err := c1.ReadFrom(rb1); err != nil {
			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
		}
		var dst Addr
		switch netstr[0] {
		case "ip":
			dst = &IPAddr{IP: IPv4(127, 0, 0, 1)}
		case "unixgram":
			continue
		default:
			dst = c2.LocalAddr()
		}
		if _, err := c1.WriteTo(wb, dst); err != nil {
			t.Fatalf("PacketConn.WriteTo failed: %v", err)
		}
		rb2 := make([]byte, 128)
		if _, err := c2.Read(rb2); err != nil {
			t.Fatalf("Conn.Read failed: %v", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

func main() {}
<commit_msg>trace: add setupTrace, gen and sq func<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"runtime/trace"
)

func setupTrace(path string) func() {

	f, err := os.Create(path)
	if err != nil {
		log.Print(err)
		return func() {}
	}

	err = trace.Start(f)
	if err != nil {
		log.Println(err)
		err = f.Close()
		if err != nil {
			log.Println(err)
		}
	}

	return func() {

		trace.Stop()

		if f != nil {
			err = f.Close()
			if err != nil {
				log.Println(err)
			}
		}
	}

}

func main() {
	stop := setupTrace("trace.out")
	defer stop()

	out := sq(sq(gen(2, 3)))

	for n := range out {
		fmt.Println(n)
	}
}

func gen(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

func sq(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * n
		}
		close(out)
	}()
	return out
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
)

var cFile = flag.String("c", "", "output file")

var cHead = `
#include <stdio.h>

int
main() {
  char array[1000];
  char *ptr = array;

`

var cTail = `
  return 0;
}
`

var indent = `  `

func addIndent(indentLevel int, s string) string {
    var indented string
    for i := 0; i < indentLevel; i++ {
        indented += indent
    }
    indented += s
    return indented
}

func makeCSource(bfSource string) string {
    cSource := cHead
    indentLevel := 1

    for _,rune := range bfSource {
		var addC string
		switch rune {
		case '>':
			addC = "++ptr;\n"
		case '<':
			addC = "--ptr;\n"
		case '+':
			addC = "++*ptr;\n"
		case '-':
			addC = "--*ptr;\n"
		case '.':
			addC = "putchar(*ptr);\n"
		case ',':
			addC = "*ptr = getchar();\n"
		case '[':
			addC = "while (*ptr) {\n"
			indentLevel += 1
		case ']':
			addC = "}\n"
			indentLevel -= 1
		default:
			continue
		}

        toAdd := addIndent(indentLevel, addC)
        cSource += toAdd
    }
    cSource += cTail
    return cSource
}

func main() {
	flag.Parse()
	if *cFile == "" {
		panic("No c destination")
	}
	if len(flag.Args()) != 1 {
		panic("No bf source")
	}
	bfFile := (flag.Args())[0]

	bfSource, err := ioutil.ReadFile(bfFile)
	if err != nil {
		panic(err)
	}
    bfString := string(bfSource)

    cSource := makeCSource(bfString)

    outBytes := []byte(cSource)
    err = ioutil.WriteFile(*cFile, outBytes, 0644)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Use iterator for rune looping.<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
)

type RuneIter struct {
	runes []rune
	cur   int
	size  int
}

type IterError struct {
	error string
}

func (e *IterError) Error() string {
	return fmt.Sprintf("%s\n", e.error)
}

func NewRuneIter(s string) RuneIter {
	runes := make([]rune, 0)
	for _,r := range s {
		runes = append(runes, r)
	}
	return RuneIter{runes, 0, len(runes)}
}

func (r *RuneIter) Peek() (rune, error) {
	if r.cur + 1 > r.size {
		return 'a', &IterError{"No more elements"}
	}
	return r.runes[r.cur + 1], nil
}

func (r *RuneIter) Next() (rune, error) {
	if r.cur + 1 > r.size {
		return 'a', &IterError{"No more elements"}
	}
	n := r.runes[r.cur]
	r.cur += 1
	return n, nil
}

var cFile = flag.String("c", "", "output file")

var cHead = `
#include <stdio.h>

int
main() {
  char array[1000];
  char *ptr = array;

`

var cTail = `
  return 0;
}
`

var indent = `  `

func addIndent(indentLevel int, s string) string {
    var indented string
    for i := 0; i < indentLevel; i++ {
        indented += indent
    }
    indented += s
    return indented
}

func makeCSource(bfSource string) string {
    cSource := cHead
    indentLevel := 1

	rIter := NewRuneIter(bfSource)

    for {
		rune,err := rIter.Next()
		if err != nil {
			break
		}
		var addC string
		switch rune {
		case '>':
			addC = "++ptr;\n"
		case '<':
			addC = "--ptr;\n"
		case '+':
			addC = "++*ptr;\n"
		case '-':
			addC = "--*ptr;\n"
		case '.':
			addC = "putchar(*ptr);\n"
		case ',':
			addC = "*ptr = getchar();\n"
		case '[':
			addC = "while (*ptr) {\n"
			indentLevel += 1
		case ']':
			addC = "}\n"
			indentLevel -= 1
		default:
			continue
		}

        toAdd := addIndent(indentLevel, addC)
        cSource += toAdd
    }
    cSource += cTail
    return cSource
}

func main() {
	flag.Parse()
	if *cFile == "" {
		panic("No c destination")
	}
	if len(flag.Args()) != 1 {
		panic("No bf source")
	}
	bfFile := (flag.Args())[0]

	bfSource, err := ioutil.ReadFile(bfFile)
	if err != nil {
		panic(err)
	}
    bfString := string(bfSource)

    cSource := makeCSource(bfString)

    outBytes := []byte(cSource)
    err = ioutil.WriteFile(*cFile, outBytes, 0644)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


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

package git

import (
	"fmt"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

type EntryMode int

// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
	ENTRY_MODE_BLOB    EntryMode = 0100644
	ENTRY_MODE_EXEC    EntryMode = 0100755
	ENTRY_MODE_SYMLINK EntryMode = 0120000
	ENTRY_MODE_COMMIT  EntryMode = 0160000
	ENTRY_MODE_TREE    EntryMode = 0040000
)

type TreeEntry struct {
	ID   sha1
	Type ObjectType

	mode EntryMode
	name string

	ptree *Tree

	commited bool

	size  int64
	sized bool
}

func (te *TreeEntry) Name() string {
	return te.name
}

func (te *TreeEntry) Size() int64 {
	if te.IsDir() {
		return 0
	} else if te.sized {
		return te.size
	}

	stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
	if err != nil {
		return 0
	}

	te.sized = true
	te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
	return te.size
}

func (te *TreeEntry) IsSubModule() bool {
	return te.mode == ENTRY_MODE_COMMIT
}

func (te *TreeEntry) IsDir() bool {
	return te.mode == ENTRY_MODE_TREE
}

func (te *TreeEntry) Blob() *Blob {
	return &Blob{
		repo:      te.ptree.repo,
		TreeEntry: te,
	}
}

type Entries []*TreeEntry

var sorter = []func(t1, t2 *TreeEntry) bool{
	func(t1, t2 *TreeEntry) bool {
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
	},
	func(t1, t2 *TreeEntry) bool {
		return t1.name < t2.name
	},
}

func (tes Entries) Len() int      { return len(tes) }
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
func (tes Entries) Less(i, j int) bool {
	t1, t2 := tes[i], tes[j]
	var k int
	for k = 0; k < len(sorter)-1; k++ {
		sort := sorter[k]
		switch {
		case sort(t1, t2):
			return true
		case sort(t2, t1):
			return false
		}
	}
	return sorter[k](t1, t2)
}

func (tes Entries) Sort() {
	sort.Sort(tes)
}

type commitInfo struct {
	id    string
	infos []interface{}
	err   error
}

// GetCommitsInfo takes advantages of concurrey to speed up getting information
// of all commits that are corresponding to these entries.
// TODO: limit max goroutines at same time
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
	if len(tes) == 0 {
		return nil, nil
	}

	revChan := make(chan commitInfo, 10)

	infoMap := make(map[string][]interface{}, len(tes))
	for i := range tes {
		if tes[i].Type != OBJECT_COMMIT {
			go func(i int) {
				cinfo := commitInfo{id: tes[i].ID.String()}
				c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
				if err != nil {
					cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
				} else {
					cinfo.infos = []interface{}{tes[i], c}
				}
				revChan <- cinfo
			}(i)
			continue
		}

		// Handle submodule
		go func(i int) {
			cinfo := commitInfo{id: tes[i].ID.String()}
			sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
				revChan <- cinfo
				return
			}

			smUrl := ""
			if sm != nil {
				smUrl = sm.Url
			}

			c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
			} else {
				cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smUrl, tes[i].ID.String())}
			}
			revChan <- cinfo
		}(i)
	}

	i := 0
	for info := range revChan {
		if info.err != nil {
			return nil, info.err
		}

		infoMap[info.id] = info.infos
		i++
		if i == len(tes) {
			break
		}
	}

	commitsInfo := make([][]interface{}, len(tes))
	for i := 0; i < len(tes); i++ {
		commitsInfo[i] = infoMap[tes[i].ID.String()]
	}
	return commitsInfo, nil
}
<commit_msg>try to fix  Duplicate of files in directory (gogs#2254 )<commit_after>// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package git

import (
	"fmt"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

type EntryMode int

// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
	ENTRY_MODE_BLOB    EntryMode = 0100644
	ENTRY_MODE_EXEC    EntryMode = 0100755
	ENTRY_MODE_SYMLINK EntryMode = 0120000
	ENTRY_MODE_COMMIT  EntryMode = 0160000
	ENTRY_MODE_TREE    EntryMode = 0040000
)

type TreeEntry struct {
	ID   sha1
	Type ObjectType

	mode EntryMode
	name string

	ptree *Tree

	commited bool

	size  int64
	sized bool
}

func (te *TreeEntry) Name() string {
	return te.name
}

func (te *TreeEntry) Size() int64 {
	if te.IsDir() {
		return 0
	} else if te.sized {
		return te.size
	}

	stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
	if err != nil {
		return 0
	}

	te.sized = true
	te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
	return te.size
}

func (te *TreeEntry) IsSubModule() bool {
	return te.mode == ENTRY_MODE_COMMIT
}

func (te *TreeEntry) IsDir() bool {
	return te.mode == ENTRY_MODE_TREE
}

func (te *TreeEntry) Blob() *Blob {
	return &Blob{
		repo:      te.ptree.repo,
		TreeEntry: te,
	}
}

type Entries []*TreeEntry

var sorter = []func(t1, t2 *TreeEntry) bool{
	func(t1, t2 *TreeEntry) bool {
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
	},
	func(t1, t2 *TreeEntry) bool {
		return t1.name < t2.name
	},
}

func (tes Entries) Len() int      { return len(tes) }
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
func (tes Entries) Less(i, j int) bool {
	t1, t2 := tes[i], tes[j]
	var k int
	for k = 0; k < len(sorter)-1; k++ {
		sort := sorter[k]
		switch {
		case sort(t1, t2):
			return true
		case sort(t2, t1):
			return false
		}
	}
	return sorter[k](t1, t2)
}

func (tes Entries) Sort() {
	sort.Sort(tes)
}

type commitInfo struct {
	id    string
	entry string
	infos []interface{}
	err   error
}

// GetCommitsInfo takes advantages of concurrey to speed up getting information
// of all commits that are corresponding to these entries.
// TODO: limit max goroutines at same time
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
	if len(tes) == 0 {
		return nil, nil
	}

	revChan := make(chan commitInfo, 10)

	infoMap := make(map[string][]interface{}, len(tes))
	for i := range tes {
		if tes[i].Type != OBJECT_COMMIT {
			go func(i int) {
				cinfo := commitInfo{id: tes[i].ID.String(), entry: tes[i].Name()}
				c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
				if err != nil {
					cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
				} else {
					cinfo.infos = []interface{}{tes[i], c}
				}
				revChan <- cinfo
			}(i)
			continue
		}

		// Handle submodule
		go func(i int) {
			cinfo := commitInfo{id: tes[i].ID.String(), entry: tes[i].Name()}
			sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
				revChan <- cinfo
				return
			}

			smUrl := ""
			if sm != nil {
				smUrl = sm.Url
			}

			c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
			} else {
				cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smUrl, tes[i].ID.String())}
			}
			revChan <- cinfo
		}(i)
	}

	i := 0
	for info := range revChan {
		if info.err != nil {
			return nil, info.err
		}

		infoMap[info.entry] = info.infos
		i++
		if i == len(tes) {
			break
		}
	}

	commitsInfo := make([][]interface{}, len(tes))
	for i := 0; i < len(tes); i++ {
		commitsInfo[i] = infoMap[tes[i].Name()]
	}
	return commitsInfo, nil
}
<|endoftext|>


<commit_before>package types

import (
	"encoding/json"
	"errors"
	"strings"
)

type Result struct {
	es  []string
	err error
}

func NewResult(err error) *Result {
	return &Result{err: err}
}

func (r *Result) One(model interface{}) error {
	if r.err != nil {
		return r.err
	}
	if len(r.es) < 1 {
		return errors.New("Result.One(): Expecting at least one model for decoding")
	}
	r.err = json.NewDecoder(strings.NewReader(r.es[0])).Decode(model)
	return r.err
}

func (r *Result) Each(model Model, do func(interface{})) error {
	if r.err != nil {
		return r.err
	}
	for _, enc := range r.es {
		instance := model.GetInstance()
		r.err = json.NewDecoder(strings.NewReader(enc)).Decode(instance)
		do(instance)
	}
	return r.err
}

func (r *Result) Update(enc string) *Result {
	if r.err == nil {
		r.es = append(r.es, enc)
	}
	return r
}

func (r *Result) NumRows() int {
	return len(r.es)
}

func (r *Result) Error() error {
	return r.err
}
<commit_msg>Added JSON encoding<commit_after>package types

import (
	"bytes"
	"encoding/json"
	"errors"
	"strings"
)

type Result struct {
	es  []string
	err error
}

func NewResult(err error) *Result {
	return &Result{err: err}
}

func (r *Result) One(model interface{}) error {
	if r.err != nil {
		return r.err
	}
	if len(r.es) < 1 {
		return errors.New("Result.One(): Expecting at least one model for decoding")
	}
	r.err = json.NewDecoder(strings.NewReader(r.es[0])).Decode(model)
	return r.err
}

func (r *Result) Each(model Model, do func(interface{})) error {
	if r.err != nil {
		return r.err
	}
	for _, enc := range r.es {
		instance := model.GetInstance()
		r.err = json.NewDecoder(strings.NewReader(enc)).Decode(instance)
		do(instance)
	}
	return r.err
}

func (r *Result) Update(enc string) *Result {
	if r.err == nil {
		r.es = append(r.es, enc)
	}
	return r
}

func (r *Result) Json() []byte {
	if len(r.es) <= 1 {
		return []byte(r.es[0])
	}
	var buf bytes.Buffer
	buf.WriteString("[")
	for i, enc := range r.es {
		buf.WriteString(enc)
		if i < len(r.es)-1 {
			buf.WriteString(",")
		}
	}
	buf.WriteString("[")
	return buf.Bytes()
}

func (r *Result) NumRows() int {
	return len(r.es)
}

func (r *Result) Error() error {
	return r.err
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/paked/engi"
	"log"
	"math/rand"
)

var (
	W Game
)

type Game struct {
	engi.World
}

func (game Game) Preload() {
	engi.Files.AddFromDir("data", false)
}

func (game *Game) Setup() {
	engi.SetBg(0x2d3739)
	game.AddSystem(&engi.RenderSystem{})
	game.AddSystem(&engi.CollisionSystem{})
	game.AddSystem(&DeathSystem{})
	game.AddSystem(&FallingSystem{})
	game.AddSystem(&ControlSystem{})
	game.AddSystem(&RockSpawnSystem{})

	guy := engi.NewEntity([]string{"RenderSystem", "ControlSystem", "RockSpawnSystem", "CollisionSystem", "DeathSystem"})
	texture := engi.Files.Image("icon.png")
	render := engi.NewRenderComponent(texture, engi.Point{4, 4}, "guy")
	collision := engi.CollisionComponent{Solid: true, Main: true}

	width := texture.Width() * render.Scale.X
	height := texture.Height() * render.Scale.Y

	space := engi.SpaceComponent{engi.Point{(engi.Width() - width) / 2, (engi.Height() - height) / 2}, width, height}

	guy.AddComponent(&render)
	guy.AddComponent(&space)
	guy.AddComponent(&collision)

	game.AddEntity(guy)
}

type ControlSystem struct {
	*engi.System
}

func (control *ControlSystem) New() {
	control.System = &engi.System{}
}

func (control ControlSystem) Name() string {
	return "ControlSystem"
}

func (control *ControlSystem) Update(entity *engi.Entity, dt float32) {
	var space *engi.SpaceComponent
	if !entity.GetComponent(&space) {
		return
	}

	speed := 400 * dt

	if engi.Keys.KEY_A.Down() {
		space.Position.X -= speed
	}

	if engi.Keys.KEY_D.Down() {
		space.Position.X += speed
	}

	if engi.Keys.KEY_W.Down() {
		space.Position.Y -= speed
	}

	if engi.Keys.KEY_S.Down() {
		space.Position.Y += speed
	}
}

type RockSpawnSystem struct {
	*engi.System
}

func (rock RockSpawnSystem) Name() string {
	return "RockSpawnSystem"
}

func (rock *RockSpawnSystem) New() {
	rock.System = &engi.System{}
}

func (rock *RockSpawnSystem) Update(entity *engi.Entity, dt float32) {
	if rand.Float32() < .96 {
		return
	}

	position := engi.Point{0, -32}
	position.X = rand.Float32() * (engi.Width())
	W.AddEntity(NewRock(position))
}

func NewRock(position engi.Point) *engi.Entity {
	rock := engi.NewEntity([]string{"RenderSystem", "FallingSystem", "CollisionSystem", "SpeedSystem"})
	texture := engi.Files.Image("rock.png")
	render := engi.NewRenderComponent(texture, engi.Point{4, 4}, "rock")
	space := engi.SpaceComponent{position, texture.Width() * render.Scale.X, texture.Height() * render.Scale.Y}
	collision := engi.CollisionComponent{Solid: true}
	rock.AddComponent(&render)
	rock.AddComponent(&space)
	rock.AddComponent(&collision)
	return rock
}

type FallingSystem struct {
	*engi.System
}

func (fs *FallingSystem) New() {
	fs.System = &engi.System{}
	//engi.Mailbox.Listen("CollisionMessage", fs)

}

func (fs FallingSystem) Name() string {
	return "FallingSystem"
}

func (fs FallingSystem) Update(entity *engi.Entity, dt float32) {
	var space *engi.SpaceComponent
	if !entity.GetComponent(&space) {
		return
	}
	space.Position.Y += 200 * dt
}

type DeathSystem struct {
	*engi.System
}

func (ds *DeathSystem) New() {
	ds.System = &engi.System{}
	engi.Mailbox.Listen("ScoreMessage", func(message interface{}) {
		collision, isCollision := message.(engi.CollisionMessage)
		if isCollision {
			log.Println(collision, message)
			log.Println("DEAD")
		}
	})

}

func (ds DeathSystem) Name() string {
	return "DeathSystem"
}

func (fs DeathSystem) Update(entity *engi.Entity, dt float32) {

}

func (fs DeathSystem) Receive(message engi.Message) {
	collision, isCollision := message.(engi.CollisionMessage)
	if isCollision {
		log.Println(collision, message)
		log.Println("DEAD")
	}
}

func main() {
	log.Println("[Game] Says hello, written in github.com/paked/engi + Go")
	W = Game{}
	engi.Open("Stream Game", 800, 800, false, &W)
}
<commit_msg>Add documentation to falling<commit_after>package main

import (
	"github.com/paked/engi"
	"log"
	"math/rand"
)

var (
	W Game
)

type Game struct {
	engi.World
}

func (game Game) Preload() {
	// Add all the files in the data directory non recursively
	engi.Files.AddFromDir("data", false)
}

func (game *Game) Setup() {
	engi.SetBg(0x2d3739)

	// Add all of the systems
	game.AddSystem(&engi.RenderSystem{})
	game.AddSystem(&engi.CollisionSystem{})
	game.AddSystem(&DeathSystem{})
	game.AddSystem(&FallingSystem{})
	game.AddSystem(&ControlSystem{})
	game.AddSystem(&RockSpawnSystem{})

	// Create new entity subscribed to all the systems!
	guy := engi.NewEntity([]string{"RenderSystem", "ControlSystem", "RockSpawnSystem", "CollisionSystem", "DeathSystem"})
	texture := engi.Files.Image("icon.png")
	render := engi.NewRenderComponent(texture, engi.Point{4, 4}, "guy")
	// Tell the collision system that this player is solid
	collision := engi.CollisionComponent{Solid: true, Main: true}

	width := texture.Width() * render.Scale.X
	height := texture.Height() * render.Scale.Y

	space := engi.SpaceComponent{engi.Point{(engi.Width() - width) / 2, (engi.Height() - height) / 2}, width, height}

	guy.AddComponent(&render)
	guy.AddComponent(&space)
	guy.AddComponent(&collision)

	game.AddEntity(guy)
}

type ControlSystem struct {
	*engi.System
}

func (control *ControlSystem) New() {
	control.System = &engi.System{}
}

func (control ControlSystem) Name() string {
	return "ControlSystem"
}

func (control *ControlSystem) Update(entity *engi.Entity, dt float32) {
	var space *engi.SpaceComponent
	if !entity.GetComponent(&space) {
		return
	}

	speed := 400 * dt

	if engi.Keys.KEY_A.Down() {
		space.Position.X -= speed
	}

	if engi.Keys.KEY_D.Down() {
		space.Position.X += speed
	}

	if engi.Keys.KEY_W.Down() {
		space.Position.Y -= speed
	}

	if engi.Keys.KEY_S.Down() {
		space.Position.Y += speed
	}
}

type RockSpawnSystem struct {
	*engi.System
}

func (rock RockSpawnSystem) Name() string {
	return "RockSpawnSystem"
}

func (rock *RockSpawnSystem) New() {
	rock.System = &engi.System{}
}

func (rock *RockSpawnSystem) Update(entity *engi.Entity, dt float32) {
	// 4% change of spawning a rock each frame
	if rand.Float32() < .96 {
		return
	}

	position := engi.Point{0, -32}
	position.X = rand.Float32() * (engi.Width())
	W.AddEntity(NewRock(position))
}

func NewRock(position engi.Point) *engi.Entity {
	rock := engi.NewEntity([]string{"RenderSystem", "FallingSystem", "CollisionSystem", "SpeedSystem"})

	texture := engi.Files.Image("rock.png")
	render := engi.NewRenderComponent(texture, engi.Point{4, 4}, "rock")
	space := engi.SpaceComponent{position, texture.Width() * render.Scale.X, texture.Height() * render.Scale.Y}
	collision := engi.CollisionComponent{Solid: true}

	rock.AddComponent(&render)
	rock.AddComponent(&space)
	rock.AddComponent(&collision)

	return rock
}

type FallingSystem struct {
	*engi.System
}

func (fs *FallingSystem) New() {
	fs.System = &engi.System{}
	//engi.Mailbox.Listen("CollisionMessage", fs)

}

func (fs FallingSystem) Name() string {
	return "FallingSystem"
}

func (fs FallingSystem) Update(entity *engi.Entity, dt float32) {
	var space *engi.SpaceComponent
	if !entity.GetComponent(&space) {
		return
	}
	space.Position.Y += 200 * dt
}

type DeathSystem struct {
	*engi.System
}

func (ds *DeathSystem) New() {
	ds.System = &engi.System{}
	// Subscribe to ScoreMessage
	engi.Mailbox.Listen("ScoreMessage", func(message interface{}) {
		collision, isCollision := message.(engi.CollisionMessage)
		if isCollision {
			log.Println(collision, message)
			log.Println("DEAD")
		}
	})

}

func (ds DeathSystem) Name() string {
	return "DeathSystem"
}

func (fs DeathSystem) Update(entity *engi.Entity, dt float32) {

}

func (fs DeathSystem) Receive(message engi.Message) {
	collision, isCollision := message.(engi.CollisionMessage)
	if isCollision {
		log.Println(collision, message)
		log.Println("DEAD")
	}
}

func main() {
	log.Println("[Game] Says hello, written in github.com/paked/engi + Go")
	W = Game{}
	engi.Open("Stream Game", 800, 800, false, &W)
}
<|endoftext|>