<commit_before>package utp

/*
#include "utp.h"
*/
import "C"
import (
	"context"
	"errors"
	"net"
	"time"
)

type Socket struct {
	pc            net.PacketConn
	ctx           *C.utp_context
	backlog       chan *Conn
	closed        bool
	conns         map[*C.utp_socket]*Conn
	nonUtpReads   chan packet
	writeDeadline time.Time
	readDeadline  time.Time
}

var (
	_ net.PacketConn = (*Socket)(nil)
)

type packet struct {
	b    []byte
	from net.Addr
}

func NewSocket(network, addr string) (*Socket, error) {
	pc, err := net.ListenPacket(network, addr)
	if err != nil {
		return nil, err
	}
	mu.Lock()
	defer mu.Unlock()
	ctx := C.utp_init(2)
	if ctx == nil {
		panic(ctx)
	}
	ctx.setCallbacks()
	if utpLogging {
		ctx.setOption(C.UTP_LOG_NORMAL, 1)
		ctx.setOption(C.UTP_LOG_MTU, 1)
		ctx.setOption(C.UTP_LOG_DEBUG, 1)
	}
	s := &Socket{
		pc:          pc,
		ctx:         ctx,
		backlog:     make(chan *Conn, 5),
		conns:       make(map[*C.utp_socket]*Conn),
		nonUtpReads: make(chan packet, 100),
	}
	libContextToSocket[ctx] = s
	go s.timeoutChecker()
	go s.packetReader()
	return s, nil
}

func (s *Socket) onLibSocketDestroyed(ls *C.utp_socket) {
	delete(s.conns, ls)
}

func (s *Socket) newConn(us *C.utp_socket) *Conn {
	c := &Conn{
		s: us,
	}
	c.cond.L = &mu
	s.conns[us] = c
	c.writeDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	c.readDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	return c
}

var reads int

func (s *Socket) packetReader() {
	var b [0x1000]byte
	for {
		n, addr, err := s.pc.ReadFrom(b[:])
		if err != nil {
			mu.Lock()
			closed := s.closed
			mu.Unlock()
			if closed {
				return
			}
			panic(err)
		}
		sa, sal := netAddrToLibSockaddr(addr)
		func() {
			mu.Lock()
			defer mu.Unlock()
			reads++
			// log.Printf("received %d bytes, %d packets", n, reads)
			if s.closed {
				return
			}
			if C.utp_process_udp(s.ctx, (*C.byte)(&b[0]), C.size_t(n), sa, sal) != 0 {
				socketUtpPacketsReceived.Add(1)
			} else {
				s.onReadNonUtp(b[:n], addr)
			}
			C.utp_issue_deferred_acks(s.ctx)
			C.utp_check_timeouts(s.ctx)
		}()
	}
}

func (s *Socket) timeoutChecker() {
	for {
		mu.Lock()
		if s.closed {
			mu.Unlock()
			return
		}
		// C.utp_issue_deferred_acks(s.ctx)
		C.utp_check_timeouts(s.ctx)
		mu.Unlock()
		time.Sleep(500 * time.Millisecond)
	}
}

func (me *Socket) Close() error {
	mu.Lock()
	defer mu.Unlock()
	if me.closed {
		return nil
	}
	C.utp_destroy(me.ctx)
	me.ctx = nil
	me.pc.Close()
	close(me.backlog)
	close(me.nonUtpReads)
	me.closed = true
	return nil
}

func (me *Socket) Addr() net.Addr {
	return me.pc.LocalAddr()
}

func (me *Socket) LocalAddr() net.Addr {
	return me.pc.LocalAddr()
}

func (s *Socket) Accept() (net.Conn, error) {
	nc, ok := <-s.backlog
	if !ok {
		return nil, errors.New("closed")
	}
	return nc, nil
}

func (s *Socket) Dial(addr string) (net.Conn, error) {
	return s.DialTimeout(addr, 0)
}

func (s *Socket) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
	ctx := context.Background()
	if timeout != 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, timeout)
		defer cancel()
	}
	return s.DialContext(ctx, addr)
}

func (s *Socket) DialContext(ctx context.Context, addr string) (net.Conn, error) {
	ua, err := net.ResolveUDPAddr(s.Addr().Network(), addr)
	if err != nil {
		panic(err)
	}
	sa, sl := netAddrToLibSockaddr(ua)
	mu.Lock()
	c := s.newConn(C.utp_create_socket(s.ctx))
	C.utp_connect(c.s, sa, sl)
	defer mu.Unlock()
	err = c.waitForConnect(ctx)
	if err != nil {
		c.close()
		return nil, err
	}
	return c, nil
}

func (s *Socket) pushBacklog(c *Conn) {
	select {
	case s.backlog <- c:
	default:
		c.close()
	}
}

func (s *Socket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
	p, ok := <-s.nonUtpReads
	if !ok {
		err = errors.New("closed")
		return
	}
	n = copy(b, p.b)
	addr = p.from
	return
}

func (s *Socket) onReadNonUtp(b []byte, from net.Addr) {
	socketNonUtpPacketsReceived.Add(1)
	select {
	case s.nonUtpReads <- packet{b, from}:
	default:
		// log.Printf("dropped non utp packet: no room in buffer")
		nonUtpPacketsDropped.Add(1)
	}
}

func (s *Socket) SetReadDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetWriteDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) WriteTo(b []byte, addr net.Addr) (int, error) {
	return s.pc.WriteTo(b, addr)
}

func (s *Socket) ReadBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_RCVBUF))
}

func (s *Socket) WriteBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_SNDBUF))
}

func (s *Socket) SetWriteBufferLen(len int) {
	mu.Lock()
	defer mu.Unlock()
	i := C.utp_context_set_option(s.ctx, C.UTP_SNDBUF, C.int(len))
	if i != 0 {
		panic(i)
	}
}
<commit_msg>Forgot to copy buffer if we're storing it for non-uTP reads<commit_after>package utp

/*
#include "utp.h"
*/
import "C"
import (
	"context"
	"errors"
	"net"
	"time"
)

type Socket struct {
	pc            net.PacketConn
	ctx           *C.utp_context
	backlog       chan *Conn
	closed        bool
	conns         map[*C.utp_socket]*Conn
	nonUtpReads   chan packet
	writeDeadline time.Time
	readDeadline  time.Time
}

var (
	_ net.PacketConn = (*Socket)(nil)
)

type packet struct {
	b    []byte
	from net.Addr
}

func NewSocket(network, addr string) (*Socket, error) {
	pc, err := net.ListenPacket(network, addr)
	if err != nil {
		return nil, err
	}
	mu.Lock()
	defer mu.Unlock()
	ctx := C.utp_init(2)
	if ctx == nil {
		panic(ctx)
	}
	ctx.setCallbacks()
	if utpLogging {
		ctx.setOption(C.UTP_LOG_NORMAL, 1)
		ctx.setOption(C.UTP_LOG_MTU, 1)
		ctx.setOption(C.UTP_LOG_DEBUG, 1)
	}
	s := &Socket{
		pc:          pc,
		ctx:         ctx,
		backlog:     make(chan *Conn, 5),
		conns:       make(map[*C.utp_socket]*Conn),
		nonUtpReads: make(chan packet, 100),
	}
	libContextToSocket[ctx] = s
	go s.timeoutChecker()
	go s.packetReader()
	return s, nil
}

func (s *Socket) onLibSocketDestroyed(ls *C.utp_socket) {
	delete(s.conns, ls)
}

func (s *Socket) newConn(us *C.utp_socket) *Conn {
	c := &Conn{
		s: us,
	}
	c.cond.L = &mu
	s.conns[us] = c
	c.writeDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	c.readDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	return c
}

var reads int

func (s *Socket) packetReader() {
	var b [0x1000]byte
	for {
		n, addr, err := s.pc.ReadFrom(b[:])
		if err != nil {
			mu.Lock()
			closed := s.closed
			mu.Unlock()
			if closed {
				return
			}
			panic(err)
		}
		sa, sal := netAddrToLibSockaddr(addr)
		func() {
			mu.Lock()
			defer mu.Unlock()
			reads++
			// log.Printf("received %d bytes, %d packets", n, reads)
			if s.closed {
				return
			}
			if C.utp_process_udp(s.ctx, (*C.byte)(&b[0]), C.size_t(n), sa, sal) != 0 {
				socketUtpPacketsReceived.Add(1)
			} else {
				s.onReadNonUtp(b[:n], addr)
			}
			C.utp_issue_deferred_acks(s.ctx)
			C.utp_check_timeouts(s.ctx)
		}()
	}
}

func (s *Socket) timeoutChecker() {
	for {
		mu.Lock()
		if s.closed {
			mu.Unlock()
			return
		}
		// C.utp_issue_deferred_acks(s.ctx)
		C.utp_check_timeouts(s.ctx)
		mu.Unlock()
		time.Sleep(500 * time.Millisecond)
	}
}

func (me *Socket) Close() error {
	mu.Lock()
	defer mu.Unlock()
	if me.closed {
		return nil
	}
	C.utp_destroy(me.ctx)
	me.ctx = nil
	me.pc.Close()
	close(me.backlog)
	close(me.nonUtpReads)
	me.closed = true
	return nil
}

func (me *Socket) Addr() net.Addr {
	return me.pc.LocalAddr()
}

func (me *Socket) LocalAddr() net.Addr {
	return me.pc.LocalAddr()
}

func (s *Socket) Accept() (net.Conn, error) {
	nc, ok := <-s.backlog
	if !ok {
		return nil, errors.New("closed")
	}
	return nc, nil
}

func (s *Socket) Dial(addr string) (net.Conn, error) {
	return s.DialTimeout(addr, 0)
}

func (s *Socket) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
	ctx := context.Background()
	if timeout != 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, timeout)
		defer cancel()
	}
	return s.DialContext(ctx, addr)
}

func (s *Socket) DialContext(ctx context.Context, addr string) (net.Conn, error) {
	ua, err := net.ResolveUDPAddr(s.Addr().Network(), addr)
	if err != nil {
		panic(err)
	}
	sa, sl := netAddrToLibSockaddr(ua)
	mu.Lock()
	c := s.newConn(C.utp_create_socket(s.ctx))
	C.utp_connect(c.s, sa, sl)
	defer mu.Unlock()
	err = c.waitForConnect(ctx)
	if err != nil {
		c.close()
		return nil, err
	}
	return c, nil
}

func (s *Socket) pushBacklog(c *Conn) {
	select {
	case s.backlog <- c:
	default:
		c.close()
	}
}

func (s *Socket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
	p, ok := <-s.nonUtpReads
	if !ok {
		err = errors.New("closed")
		return
	}
	n = copy(b, p.b)
	addr = p.from
	return
}

func (s *Socket) onReadNonUtp(b []byte, from net.Addr) {
	socketNonUtpPacketsReceived.Add(1)
	select {
	case s.nonUtpReads <- packet{append([]byte(nil), b...), from}:
	default:
		// log.Printf("dropped non utp packet: no room in buffer")
		nonUtpPacketsDropped.Add(1)
	}
}

func (s *Socket) SetReadDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetWriteDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) WriteTo(b []byte, addr net.Addr) (int, error) {
	return s.pc.WriteTo(b, addr)
}

func (s *Socket) ReadBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_RCVBUF))
}

func (s *Socket) WriteBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_SNDBUF))
}

func (s *Socket) SetWriteBufferLen(len int) {
	mu.Lock()
	defer mu.Unlock()
	i := C.utp_context_set_option(s.ctx, C.UTP_SNDBUF, C.int(len))
	if i != 0 {
		panic(i)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Source struct {
	url *url.URL
}

func (s *Source) String() string {
	return s.url.String()
}

func NewSource(urlString string) (*Source, error) {
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}

	switch u.Scheme {
	case "file", "http", "https":
		return &Source{url: u}, nil
	}

	return nil, fmt.Errorf("unknown scheme %q", u.Scheme)
}

func (s *Source) Read() ([]byte, error) {
	switch s.url.Scheme {
	case "file":
		return ioutil.ReadFile(s.url.Path)
	case "http", "https":
		resp, err := http.Get(s.url.String())
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()

		if resp.StatusCode != http.StatusOK {
			return nil, err
		}

		return ioutil.ReadAll(resp.Body)
	}

	return nil, fmt.Errorf("unknown scheme %q", s.url.Scheme)
}
<commit_msg>Fix Source.Read to return a non-nil error when HTTP status != 200<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Source struct {
	url *url.URL
}

func (s *Source) String() string {
	return s.url.String()
}

func NewSource(urlString string) (*Source, error) {
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}

	switch u.Scheme {
	case "file", "http", "https":
		return &Source{url: u}, nil
	}

	return nil, fmt.Errorf("unknown scheme %q", u.Scheme)
}

func (s *Source) Read() ([]byte, error) {
	switch s.url.Scheme {
	case "file":
		return ioutil.ReadFile(s.url.Path)
	case "http", "https":
		resp, err := http.Get(s.url.String())
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()

		if resp.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("status code %d", resp.StatusCode)
		}

		return ioutil.ReadAll(resp.Body)
	}

	return nil, fmt.Errorf("unknown scheme %q", s.url.Scheme)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
	"log"

	"github.com/jmcvetta/napping"
	"bytes"
)

type Configuration struct {
	LogFilePath string
	Interval    int
	DebugMode   bool
	TraceMode   bool
	LogStashUrl string
	LgLogin     string // logstash login
	LgPassword  string // logstash password
	NatsUrls    []string
}
type NatsNodeTopInfo struct {
	Varz  Varz
	Connz Connz
}
type Cluster struct {
	Addr         string
	Cluster_port int
}
type Varz struct {
	Server_id         string
	Host              string
	Addr              string
	Http_host         string
	Cluster           Cluster
	Start             string
	Now               time.Time
	Uptime            string
	Mem               float32
	Cpu               float32
	Connections       int
	Total_connections int
	Routes            int
	Remotes           int
	In_msgs           int
	Out_msgs          int
	In_bytes          int
	Out_bytes         int
	In_msgs_sec       int
	Out_msgs_sec      int
	In_bytes_sec      int
	Out_bytes_sec     int
	Slow_consumers    int
	Subscriptions     int
}
type Connection struct {
	Сid           int
	Ip            string
	Port          int
	Start         string
	Last_activity string
	Uptime        string
	Pending_bytes int
	In_msgs       int
	Out_msgs      int
	In_bytes      int
	Out_bytes     int
}
type Connz struct {
	Now             string
	Num_connections int
	Total           int
	Offset          int
	Limit           int
	Connections     []Connection
}
type PrevInOutValues struct {
	In_msgs   int
	Out_msgs  int
	In_bytes  int
	Out_bytes int

	Now       time.Time
}
type InOutPerSec struct {
	In_msgs_sec   int
	Out_msgs_sec  int
	In_bytes_sec  int
	Out_bytes_sec int
}

var prev_vals map[string]*PrevInOutValues = make(map[string]*PrevInOutValues)

func main() {

	config := Configuration{}

	configPathCL := flag.String("c", "", "path to config file")
	logFilePathCL := flag.String("l", "", "path to log file")
	isDebugCL := flag.Bool("d", false, "DEBUG mode")
	isTraceCL := flag.Bool("t", false, "TRACE mode")

	setFlag(flag.CommandLine)
	flag.Parse()

	config = readConfig(*configPathCL)

	isDebug := config.DebugMode
	isTrace := config.TraceMode

	if *isDebugCL {
		isDebug = *isDebugCL
	}

	if *isTraceCL {
		isTrace = *isTraceCL
	}

	setLogOutput(config, *logFilePathCL)

	httpClient := http.Client{}
	httpClient.Timeout = time.Duration(300) * time.Millisecond
	sessionToNats := napping.Session{Client: &httpClient}
	sessionToLogstash := napping.Session{Userinfo: url.UserPassword(config.LgLogin, config.LgPassword)}

	e := HttpError{}

	log.Printf("NATS-ELK forwarder started\n")
	log.Printf("Interval of requests: %d ms\n", config.Interval)

	for true {

		for _, url := range config.NatsUrls {

			varz := Varz{}
			connzs := Connz{}
			natsNodeTopInfo := NatsNodeTopInfo{}

			varzUrl := url + "/varz"
			connzUrl := url + "/connz"

			varzResponse, err := sessionToNats.Get(varzUrl, nil, &varz, &e)

			if err != nil {
				log.Printf("%v\n", err)
				continue
			}

			connzResponse, err := sessionToNats.Get(connzUrl, nil, &connzs, &e)

			if err != nil {
				log.Printf("%v\n", err)
				continue
			}

			if varzResponse.Status() == 200 && connzResponse.Status() == 200 {

				if isDebug {
					log.Printf("Get data from nats node (%v) - Success\n", url)
				}

				perSecValues := getPerSecValues(url, varz)

				varz.In_bytes_sec = perSecValues.In_bytes_sec
				varz.Out_bytes_sec = perSecValues.Out_bytes_sec
				varz.In_msgs_sec = perSecValues.In_msgs_sec
				varz.Out_msgs_sec = perSecValues.Out_msgs_sec

				varz.Mem = varz.Mem / 1024 / 1024 // to MB
				natsNodeTopInfo.Varz = varz
				natsNodeTopInfo.Connz = connzs

				if isTrace {
					printPrettyJson(natsNodeTopInfo)
				}

				logstashResponse, err := sessionToLogstash.Post(config.LogStashUrl, natsNodeTopInfo, nil, &e)

				if err != nil && isDebug {
					log.Printf("Sending to logstash -> Error: ")
					log.Printf("%v\n", err)
				}
				if logstashResponse.Status() == 200 && isDebug {
					log.Printf("Sending to logstash (%v): Success\n", config.LogStashUrl)
				}
			}
		}
		time.Sleep(time.Duration(config.Interval) * time.Millisecond)
	}
}
func getPerSecValues(url string, varz Varz) InOutPerSec {
	inOutPerSec := InOutPerSec{}

	if prev_vals[url] == nil {

		prev_vals[url] = &PrevInOutValues{}

		prev_vals[url].In_bytes = varz.In_bytes
		prev_vals[url].Out_bytes = varz.Out_bytes
		prev_vals[url].In_msgs = varz.In_msgs
		prev_vals[url].Out_msgs = varz.Out_msgs
		prev_vals[url].Now = varz.Now

		return InOutPerSec{}
	}

	// calculate
	in_bytes_delta := varz.In_bytes - prev_vals[url].In_bytes
	out_bytes_delta := varz.Out_bytes - prev_vals[url].Out_bytes

	in_msgs_delta := varz.In_msgs - prev_vals[url].In_msgs
	out_msgs_delta := varz.Out_msgs - prev_vals[url].Out_msgs

	sec := varz.Now.Second() - prev_vals[url].Now.Second()

	inOutPerSec.In_bytes_sec = in_bytes_delta / sec
	inOutPerSec.Out_bytes_sec = out_bytes_delta / sec
	inOutPerSec.In_msgs_sec = in_msgs_delta / sec
	inOutPerSec.Out_msgs_sec = out_msgs_delta / sec

	// save prev.values
	prev_vals[url].In_bytes = varz.In_bytes
	prev_vals[url].Out_bytes = varz.Out_bytes
	prev_vals[url].In_msgs = varz.In_msgs
	prev_vals[url].Out_msgs = varz.Out_msgs
	prev_vals[url].Now = varz.Now

	// return result
	return inOutPerSec
}
func readConfig(filepath string) Configuration {

	file, _ := os.Open(filepath)
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err := decoder.Decode(&configuration)

	if err != nil {
		log.Println("error:", err)
	}

	return configuration
}

type HttpError struct {
	Message string
	Errors  []struct {
		Resource string
		Field    string
		Code     string
	}
}

func setFlag(flag *flag.FlagSet) {
	flag.Usage = func() {
		showHelp()
	}
}
func showHelp() {
	fmt.Println(`
Usage: CLI Template [OPTIONS]
Options:
    -c, --config     Path to config file.
    -l, --log        Path to log file.
    -d, --debug      DEBUG mode.
    -t, --trace      TRACE mode.
    -h, --help       prints this help info.
    `)
}
func setLogOutput(config Configuration, logFilePathCL string) {

	if len(config.LogFilePath) > 0 || len(logFilePathCL) > 0 {

		logFilePath := ""

		if len(config.LogFilePath) > 0 {
			logFilePath = config.LogFilePath
		}
		if len(logFilePathCL) > 0 {
			logFilePath = logFilePathCL
		}

		file, err := os.OpenFile(logFilePath, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)

		if err != nil {
			log.Fatalf("error opening file: %v", err)
		}

		log.SetOutput(file)
	}
}
func printPrettyJson(info NatsNodeTopInfo){
	var prettyJSON bytes.Buffer

	body, err := json.Marshal(info)

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

	error := json.Indent(&prettyJSON, body, "", "\t")
	if error != nil {
		log.Println("JSON parse error: ", error)
		return
	}

	log.Println(string(prettyJSON.Bytes()))
}
<commit_msg>Fixed error connection to logstash<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
	"log"

	"github.com/jmcvetta/napping"
	"bytes"
)

type Configuration struct {
	LogFilePath string
	Interval    int
	DebugMode   bool
	TraceMode   bool
	LogStashUrl string
	LgLogin     string // logstash login
	LgPassword  string // logstash password
	NatsUrls    []string
}
type NatsNodeTopInfo struct {
	Varz  Varz
	Connz Connz
}
type Cluster struct {
	Addr         string
	Cluster_port int
}
type Varz struct {
	Server_id         string
	Host              string
	Addr              string
	Http_host         string
	Cluster           Cluster
	Start             string
	Now               time.Time
	Uptime            string
	Mem               float32
	Cpu               float32
	Connections       int
	Total_connections int
	Routes            int
	Remotes           int
	In_msgs           int
	Out_msgs          int
	In_bytes          int
	Out_bytes         int
	In_msgs_sec       int
	Out_msgs_sec      int
	In_bytes_sec      int
	Out_bytes_sec     int
	Slow_consumers    int
	Subscriptions     int
}
type Connection struct {
	Сid           int
	Ip            string
	Port          int
	Start         string
	Last_activity string
	Uptime        string
	Pending_bytes int
	In_msgs       int
	Out_msgs      int
	In_bytes      int
	Out_bytes     int
}
type Connz struct {
	Now             string
	Num_connections int
	Total           int
	Offset          int
	Limit           int
	Connections     []Connection
}
type PrevInOutValues struct {
	In_msgs   int
	Out_msgs  int
	In_bytes  int
	Out_bytes int

	Now       time.Time
}
type InOutPerSec struct {
	In_msgs_sec   int
	Out_msgs_sec  int
	In_bytes_sec  int
	Out_bytes_sec int
}

var prev_vals map[string]*PrevInOutValues = make(map[string]*PrevInOutValues)

func main() {

	config := Configuration{}

	configPathCL := flag.String("c", "", "path to config file")
	logFilePathCL := flag.String("l", "", "path to log file")
	isDebugCL := flag.Bool("d", false, "DEBUG mode")
	isTraceCL := flag.Bool("t", false, "TRACE mode")

	setFlag(flag.CommandLine)
	flag.Parse()

	config = readConfig(*configPathCL)

	isDebug := config.DebugMode
	isTrace := config.TraceMode

	if *isDebugCL {
		isDebug = *isDebugCL
	}

	if *isTraceCL {
		isTrace = *isTraceCL
	}

	setLogOutput(config, *logFilePathCL)

	httpClient := http.Client{}
	httpClient.Timeout = time.Duration(300) * time.Millisecond
	sessionToNats := napping.Session{Client: &httpClient}
	sessionToLogstash := napping.Session{Userinfo: url.UserPassword(config.LgLogin, config.LgPassword)}

	e := HttpError{}

	log.Printf("NATS-ELK forwarder started\n")
	log.Printf("Interval of requests: %d ms\n", config.Interval)

	for true {

		for _, url := range config.NatsUrls {

			varz := Varz{}
			connzs := Connz{}
			natsNodeTopInfo := NatsNodeTopInfo{}

			varzUrl := url + "/varz"
			connzUrl := url + "/connz"

			varzResponse, err := sessionToNats.Get(varzUrl, nil, &varz, &e)

			if err != nil {
				log.Printf("%v\n", err)
				continue
			}

			connzResponse, err := sessionToNats.Get(connzUrl, nil, &connzs, &e)

			if err != nil {
				log.Printf("%v\n", err)
				continue
			}

			if varzResponse.Status() == 200 && connzResponse.Status() == 200 {

				if isDebug {
					log.Printf("Get data from nats node (%v) - Success\n", url)
				}

				perSecValues := getPerSecValues(url, varz)

				varz.In_bytes_sec = perSecValues.In_bytes_sec
				varz.Out_bytes_sec = perSecValues.Out_bytes_sec
				varz.In_msgs_sec = perSecValues.In_msgs_sec
				varz.Out_msgs_sec = perSecValues.Out_msgs_sec

				varz.Mem = varz.Mem / 1024 / 1024 // to MB
				natsNodeTopInfo.Varz = varz
				natsNodeTopInfo.Connz = connzs

				if isTrace {
					printPrettyJson(natsNodeTopInfo)
				}

				logstashResponse, err := sessionToLogstash.Post(config.LogStashUrl, natsNodeTopInfo, nil, &e)

				if err != nil {
					log.Printf("Sending to logstash -> Error: ")
					log.Printf("%v\n", err)
					continue
				}
				if logstashResponse.Status() == 200 && isDebug {
					log.Printf("Sending to logstash (%v): Success\n", config.LogStashUrl)
				}
			}
		}
		time.Sleep(time.Duration(config.Interval) * time.Millisecond)
	}
}
func getPerSecValues(url string, varz Varz) InOutPerSec {
	inOutPerSec := InOutPerSec{}

	if prev_vals[url] == nil {

		prev_vals[url] = &PrevInOutValues{}

		prev_vals[url].In_bytes = varz.In_bytes
		prev_vals[url].Out_bytes = varz.Out_bytes
		prev_vals[url].In_msgs = varz.In_msgs
		prev_vals[url].Out_msgs = varz.Out_msgs
		prev_vals[url].Now = varz.Now

		return InOutPerSec{}
	}

	// calculate
	in_bytes_delta := varz.In_bytes - prev_vals[url].In_bytes
	out_bytes_delta := varz.Out_bytes - prev_vals[url].Out_bytes

	in_msgs_delta := varz.In_msgs - prev_vals[url].In_msgs
	out_msgs_delta := varz.Out_msgs - prev_vals[url].Out_msgs

	sec := varz.Now.Second() - prev_vals[url].Now.Second()

	inOutPerSec.In_bytes_sec = in_bytes_delta / sec
	inOutPerSec.Out_bytes_sec = out_bytes_delta / sec
	inOutPerSec.In_msgs_sec = in_msgs_delta / sec
	inOutPerSec.Out_msgs_sec = out_msgs_delta / sec

	// save prev.values
	prev_vals[url].In_bytes = varz.In_bytes
	prev_vals[url].Out_bytes = varz.Out_bytes
	prev_vals[url].In_msgs = varz.In_msgs
	prev_vals[url].Out_msgs = varz.Out_msgs
	prev_vals[url].Now = varz.Now

	// return result
	return inOutPerSec
}
func readConfig(filepath string) Configuration {

	file, _ := os.Open(filepath)
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err := decoder.Decode(&configuration)

	if err != nil {
		log.Println("error:", err)
	}

	return configuration
}

type HttpError struct {
	Message string
	Errors  []struct {
		Resource string
		Field    string
		Code     string
	}
}

func setFlag(flag *flag.FlagSet) {
	flag.Usage = func() {
		showHelp()
	}
}
func showHelp() {
	fmt.Println(`
Usage: CLI Template [OPTIONS]
Options:
    -c, --config     Path to config file.
    -l, --log        Path to log file.
    -d, --debug      DEBUG mode.
    -t, --trace      TRACE mode.
    -h, --help       prints this help info.
    `)
}
func setLogOutput(config Configuration, logFilePathCL string) {

	if len(config.LogFilePath) > 0 || len(logFilePathCL) > 0 {

		logFilePath := ""

		if len(config.LogFilePath) > 0 {
			logFilePath = config.LogFilePath
		}
		if len(logFilePathCL) > 0 {
			logFilePath = logFilePathCL
		}

		file, err := os.OpenFile(logFilePath, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)

		if err != nil {
			log.Fatalf("error opening file: %v", err)
		}

		log.SetOutput(file)
	}
}
func printPrettyJson(info NatsNodeTopInfo){
	var prettyJSON bytes.Buffer

	body, err := json.Marshal(info)

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

	error := json.Indent(&prettyJSON, body, "", "\t")
	if error != nil {
		log.Println("JSON parse error: ", error)
		return
	}

	log.Println(string(prettyJSON.Bytes()))
}
<|endoftext|>


<commit_before>// Copyright 2011 Numrotron Inc.
// Use of this source code is governed by an MIT-style license
// that can be found in the LICENSE file.
//
// Developed at www.stathat.com by Patrick Crosby
// Contact us on twitter with any questions:  twitter.com/stat_hat

// splint is a little Go application to analyze Go source files.  It finds any functions that are
// too long or have too many parameters or results.
package main // import "stathat.com/c/splint"

import (
	"encoding/json"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path"
)

var statementThreshold = flag.Int("s", 30, "function statement count threshold")
var paramThreshold = flag.Int("p", 5, "parameter list length threshold")
var resultThreshold = flag.Int("r", 5, "result list length threshold")
var ifChainThreshold = flag.Int("c", 2, "if/else chain length threshold")
var outputJSON = flag.Bool("j", false, "output results as json")
var ignoreTestFiles = flag.Bool("i", true, "ignore test files")

// Parser parses go source files, looking for potentially complex
// code.
type Parser struct {
	filename string
	first    bool
	summary  *Summary
	fileset  *token.FileSet
}

// Offender contains the file, function, position, and count of
// a block of code that splint has recognized as an issue.
type Offender struct {
	Filename string
	Function string
	Count    int
	Position token.Position
}

func (o *Offender) warning(msg string) {
	if *outputJSON {
		return
	}
	fmt.Printf("%s:\tfunction %s %s: %d\n", o.Position, o.Function, msg, o.Count)
}

func (o *Offender) warnNoCount(msg string) {
	if *outputJSON {
		return
	}
	fmt.Printf("%s:\tfunction %s %s\n", o.Position, o.Function, msg)
}

// Summary is a collection of Offenders for all the different
// checks that splint performs.
type Summary struct {
	Statement []*Offender
	Param     []*Offender
	Result    []*Offender
	EmptyIfs  []*Offender
	IfChains  []*Offender

	// redundant, but using these for easy json output
	NumAboveStatementThreshold int
	NumAboveParamThreshold     int
	NumAboveResultThreshold    int
	NumIfChains                int
	NumEmptyIfs                int
}

func (s *Summary) addStatement(o *Offender) {
	s.Statement = append(s.Statement, o)
	s.NumAboveStatementThreshold++
	o.warning("too long")
}

func (s *Summary) addParam(o *Offender) {
	s.Param = append(s.Param, o)
	s.NumAboveParamThreshold++
	o.warning("too many params")
}

func (s *Summary) addResult(o *Offender) {
	s.Result = append(s.Result, o)
	s.NumAboveResultThreshold++
	o.warning("too many results")
}

func (s *Summary) addEmptyIfBody(o *Offender) {
	s.EmptyIfs = append(s.EmptyIfs, o)
	s.NumEmptyIfs++
	o.warnNoCount("if with empty body")
}

func (s *Summary) addIfChain(o *Offender) {
	s.IfChains = append(s.IfChains, o)
	s.NumIfChains++
	o.warning("long if/else chain")
}

// NewParser creates a splint parser for a file.
func NewParser(filename string, summary *Summary) *Parser {
	return &Parser{filename: filename, first: true, summary: summary}
}

func statementCount(n ast.Node) int {
	total := 0
	counter := func(node ast.Node) bool {
		switch node.(type) {
		case ast.Stmt:
			total++
		}
		return true
	}
	ast.Inspect(n, counter)
	return total
}

func (p *Parser) offender(function string, count int, pos token.Pos) *Offender {
	return &Offender{
		Filename: p.filename,
		Function: function,
		Count:    count,
		Position: p.fileset.Position(pos),
	}
}

func (p *Parser) checkFuncLength(x *ast.FuncDecl) {
	numStatements := statementCount(x)
	if numStatements <= *statementThreshold {
		return
	}

	p.summary.addStatement(p.offender(x.Name.String(), numStatements, x.Pos()))
}

func (p *Parser) checkParamCount(x *ast.FuncDecl) {
	numFields := x.Type.Params.NumFields()
	if numFields <= *paramThreshold {
		return
	}

	p.summary.addParam(p.offender(x.Name.String(), numFields, x.Pos()))
}

func (p *Parser) checkResultCount(x *ast.FuncDecl) {
	numResults := x.Type.Results.NumFields()
	if numResults <= *resultThreshold {
		return
	}

	p.summary.addResult(p.offender(x.Name.String(), numResults, x.Pos()))
}

func (p *Parser) checkEmptyIfs(x *ast.FuncDecl) {
	findIf := func(node ast.Node) bool {
		switch y := node.(type) {
		case *ast.IfStmt:
			if y.Body == nil || len(y.Body.List) == 0 {
				p.summary.addEmptyIfBody(p.offender(x.Name.String(), 0, y.Pos()))
			}
		}
		return true
	}
	ast.Inspect(x, findIf)
}

func chainLength(x *ast.IfStmt) int {
	if x.Else == nil {
		return 0
	}
	if ifst, ok := x.Else.(*ast.IfStmt); ok {
		return 1 + chainLength(ifst)
	}
	return 1
}

func (p *Parser) checkIfChains(x *ast.FuncDecl) {
	findIf := func(node ast.Node) bool {
		switch y := node.(type) {
		case *ast.IfStmt:
			n := chainLength(y)
			if n > *ifChainThreshold {
				p.summary.addIfChain(p.offender(x.Name.String(), n, y.Pos()))
			}
			return false // don't go any deeper
		}
		return true
	}
	ast.Inspect(x, findIf)
}

func (p *Parser) examineFunc(x *ast.FuncDecl) {
	p.checkFuncLength(x)
	p.checkParamCount(x)
	p.checkResultCount(x)
	p.checkEmptyIfs(x)
	p.checkIfChains(x)
}

func (p *Parser) examineDecls(tree *ast.File) {
	for _, v := range tree.Decls {
		switch x := v.(type) {
		case *ast.FuncDecl:
			p.examineFunc(x)
		}
	}
}

// Parse parses a file, looking for issues in functions.
func (p *Parser) Parse() {
	p.fileset = token.NewFileSet()
	tree, err := parser.ParseFile(p.fileset, p.filename, nil, 0)
	if err != nil {
		fmt.Printf("error parsing %s: %s\n", p.filename, err)
		return
	}

	p.examineDecls(tree)
}

func isTestFile(filename string) bool {
	base := path.Base(filename)
	match, err := path.Match("*_test.go", base)
	if err != nil {
		fmt.Println("match error:", err)
		return false
	}
	return match
}

func parseFile(filename string, summary *Summary) {
	if *ignoreTestFiles && isTestFile(filename) {
		return
	}
	parser := NewParser(filename, summary)
	parser.Parse()
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) == 0 {
		fmt.Println("Usage: splint [options] <go file>...")
		flag.PrintDefaults()
		os.Exit(1)
	}

	summary := new(Summary)

	for _, v := range args {
		parseFile(v, summary)
	}

	if *outputJSON {
		data, err := json.MarshalIndent(summary, "", "\t")
		if err != nil {
			fmt.Println("json encode error:", err)
		}
		fmt.Println(string(data))

	} else {
		fmt.Println()
		fmt.Println("Number of functions above statement threshold:", summary.NumAboveStatementThreshold)
		fmt.Println("Number of functions above param threshold:", summary.NumAboveParamThreshold)
		fmt.Println("Number of functions above result threshold:", summary.NumAboveResultThreshold)
		fmt.Println("Number of long if/else chains:", summary.NumIfChains)
		fmt.Println("Number of empty if bodies:", summary.NumEmptyIfs)
	}
}
<commit_msg>exit 1 if not clean summary<commit_after>// Copyright 2011 Numrotron Inc.
// Use of this source code is governed by an MIT-style license
// that can be found in the LICENSE file.
//
// Developed at www.stathat.com by Patrick Crosby
// Contact us on twitter with any questions:  twitter.com/stat_hat

// splint is a little Go application to analyze Go source files.  It finds any functions that are
// too long or have too many parameters or results.
package main // import "stathat.com/c/splint"

import (
	"encoding/json"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path"
)

var statementThreshold = flag.Int("s", 30, "function statement count threshold")
var paramThreshold = flag.Int("p", 5, "parameter list length threshold")
var resultThreshold = flag.Int("r", 5, "result list length threshold")
var ifChainThreshold = flag.Int("c", 2, "if/else chain length threshold")
var outputJSON = flag.Bool("j", false, "output results as json")
var ignoreTestFiles = flag.Bool("i", true, "ignore test files")

// Parser parses go source files, looking for potentially complex
// code.
type Parser struct {
	filename string
	first    bool
	summary  *Summary
	fileset  *token.FileSet
}

// Offender contains the file, function, position, and count of
// a block of code that splint has recognized as an issue.
type Offender struct {
	Filename string
	Function string
	Count    int
	Position token.Position
}

func (o *Offender) warning(msg string) {
	if *outputJSON {
		return
	}
	fmt.Printf("%s:\tfunction %s %s: %d\n", o.Position, o.Function, msg, o.Count)
}

func (o *Offender) warnNoCount(msg string) {
	if *outputJSON {
		return
	}
	fmt.Printf("%s:\tfunction %s %s\n", o.Position, o.Function, msg)
}

// Summary is a collection of Offenders for all the different
// checks that splint performs.
type Summary struct {
	Statement []*Offender
	Param     []*Offender
	Result    []*Offender
	EmptyIfs  []*Offender
	IfChains  []*Offender

	// redundant, but using these for easy json output
	NumAboveStatementThreshold int
	NumAboveParamThreshold     int
	NumAboveResultThreshold    int
	NumIfChains                int
	NumEmptyIfs                int
}

func (s *Summary) IsClean() bool {
	return len(s.Statement) == 0 && len(s.Param) == 0 && len(s.Result) == 0 && len(s.EmptyIfs) == 0 && len(s.IfChains) == 0
}

func (s *Summary) addStatement(o *Offender) {
	s.Statement = append(s.Statement, o)
	s.NumAboveStatementThreshold++
	o.warning("too long")
}

func (s *Summary) addParam(o *Offender) {
	s.Param = append(s.Param, o)
	s.NumAboveParamThreshold++
	o.warning("too many params")
}

func (s *Summary) addResult(o *Offender) {
	s.Result = append(s.Result, o)
	s.NumAboveResultThreshold++
	o.warning("too many results")
}

func (s *Summary) addEmptyIfBody(o *Offender) {
	s.EmptyIfs = append(s.EmptyIfs, o)
	s.NumEmptyIfs++
	o.warnNoCount("if with empty body")
}

func (s *Summary) addIfChain(o *Offender) {
	s.IfChains = append(s.IfChains, o)
	s.NumIfChains++
	o.warning("long if/else chain")
}

// NewParser creates a splint parser for a file.
func NewParser(filename string, summary *Summary) *Parser {
	return &Parser{filename: filename, first: true, summary: summary}
}

func statementCount(n ast.Node) int {
	total := 0
	counter := func(node ast.Node) bool {
		switch node.(type) {
		case ast.Stmt:
			total++
		}
		return true
	}
	ast.Inspect(n, counter)
	return total
}

func (p *Parser) offender(function string, count int, pos token.Pos) *Offender {
	return &Offender{
		Filename: p.filename,
		Function: function,
		Count:    count,
		Position: p.fileset.Position(pos),
	}
}

func (p *Parser) checkFuncLength(x *ast.FuncDecl) {
	numStatements := statementCount(x)
	if numStatements <= *statementThreshold {
		return
	}

	p.summary.addStatement(p.offender(x.Name.String(), numStatements, x.Pos()))
}

func (p *Parser) checkParamCount(x *ast.FuncDecl) {
	numFields := x.Type.Params.NumFields()
	if numFields <= *paramThreshold {
		return
	}

	p.summary.addParam(p.offender(x.Name.String(), numFields, x.Pos()))
}

func (p *Parser) checkResultCount(x *ast.FuncDecl) {
	numResults := x.Type.Results.NumFields()
	if numResults <= *resultThreshold {
		return
	}

	p.summary.addResult(p.offender(x.Name.String(), numResults, x.Pos()))
}

func (p *Parser) checkEmptyIfs(x *ast.FuncDecl) {
	findIf := func(node ast.Node) bool {
		switch y := node.(type) {
		case *ast.IfStmt:
			if y.Body == nil || len(y.Body.List) == 0 {
				p.summary.addEmptyIfBody(p.offender(x.Name.String(), 0, y.Pos()))
			}
		}
		return true
	}
	ast.Inspect(x, findIf)
}

func chainLength(x *ast.IfStmt) int {
	if x.Else == nil {
		return 0
	}
	if ifst, ok := x.Else.(*ast.IfStmt); ok {
		return 1 + chainLength(ifst)
	}
	return 1
}

func (p *Parser) checkIfChains(x *ast.FuncDecl) {
	findIf := func(node ast.Node) bool {
		switch y := node.(type) {
		case *ast.IfStmt:
			n := chainLength(y)
			if n > *ifChainThreshold {
				p.summary.addIfChain(p.offender(x.Name.String(), n, y.Pos()))
			}
			return false // don't go any deeper
		}
		return true
	}
	ast.Inspect(x, findIf)
}

func (p *Parser) examineFunc(x *ast.FuncDecl) {
	p.checkFuncLength(x)
	p.checkParamCount(x)
	p.checkResultCount(x)
	p.checkEmptyIfs(x)
	p.checkIfChains(x)
}

func (p *Parser) examineDecls(tree *ast.File) {
	for _, v := range tree.Decls {
		switch x := v.(type) {
		case *ast.FuncDecl:
			p.examineFunc(x)
		}
	}
}

// Parse parses a file, looking for issues in functions.
func (p *Parser) Parse() {
	p.fileset = token.NewFileSet()
	tree, err := parser.ParseFile(p.fileset, p.filename, nil, 0)
	if err != nil {
		fmt.Printf("error parsing %s: %s\n", p.filename, err)
		return
	}

	p.examineDecls(tree)
}

func isTestFile(filename string) bool {
	base := path.Base(filename)
	match, err := path.Match("*_test.go", base)
	if err != nil {
		fmt.Println("match error:", err)
		return false
	}
	return match
}

func parseFile(filename string, summary *Summary) {
	if *ignoreTestFiles && isTestFile(filename) {
		return
	}
	parser := NewParser(filename, summary)
	parser.Parse()
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) == 0 {
		fmt.Println("Usage: splint [options] <go file>...")
		flag.PrintDefaults()
		os.Exit(1)
	}

	summary := new(Summary)

	for _, v := range args {
		parseFile(v, summary)
	}

	if *outputJSON {
		data, err := json.MarshalIndent(summary, "", "\t")
		if err != nil {
			fmt.Println("json encode error:", err)
		}
		fmt.Println(string(data))

	} else {
		fmt.Println()
		fmt.Println("Number of functions above statement threshold:", summary.NumAboveStatementThreshold)
		fmt.Println("Number of functions above param threshold:", summary.NumAboveParamThreshold)
		fmt.Println("Number of functions above result threshold:", summary.NumAboveResultThreshold)
		fmt.Println("Number of long if/else chains:", summary.NumIfChains)
		fmt.Println("Number of empty if bodies:", summary.NumEmptyIfs)
		if !summary.IsClean() {
			os.Exit(1)
		}
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"strings"

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
)

func resourceAwsKeyPair() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsKeyPairCreate,
		Read:   resourceAwsKeyPairRead,
		Update: nil,
		Delete: resourceAwsKeyPairDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		SchemaVersion: 1,
		MigrateState:  resourceAwsKeyPairMigrateState,

		Schema: map[string]*schema.Schema{
			"key_name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"key_name_prefix"},
				ValidateFunc:  validateMaxLength(255),
			},
			"key_name_prefix": {
				Type:          schema.TypeString,
				Optional:      true,
				ForceNew:      true,
				ConflictsWith: []string{"key_name"},
				ValidateFunc:  validateMaxLength(255 - resource.UniqueIDSuffixLength),
			},
			"public_key": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				StateFunc: func(v interface{}) string {
					switch v.(type) {
					case string:
						return strings.TrimSpace(v.(string))
					default:
						return ""
					}
				},
			},
			"fingerprint": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsKeyPairCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	var keyName string
	if v, ok := d.GetOk("key_name"); ok {
		keyName = v.(string)
	} else if v, ok := d.GetOk("key_name_prefix"); ok {
		keyName = resource.PrefixedUniqueId(v.(string))
		d.Set("key_name", keyName)
	} else {
		keyName = resource.UniqueId()
		d.Set("key_name", keyName)
	}

	publicKey := d.Get("public_key").(string)
	req := &ec2.ImportKeyPairInput{
		KeyName:           aws.String(keyName),
		PublicKeyMaterial: []byte(publicKey),
	}
	resp, err := conn.ImportKeyPair(req)
	if err != nil {
		return fmt.Errorf("Error import KeyPair: %s", err)
	}

        d.Set("fingerprint", *resp.KeyFingerprint)
	d.SetId(*resp.KeyName)
	return nil
}

func resourceAwsKeyPairRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	req := &ec2.DescribeKeyPairsInput{
		KeyNames: []*string{aws.String(d.Id())},
	}
	resp, err := conn.DescribeKeyPairs(req)
	if err != nil {
		awsErr, ok := err.(awserr.Error)
		if ok && awsErr.Code() == "InvalidKeyPair.NotFound" {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving KeyPair: %s", err)
	}

	for _, keyPair := range resp.KeyPairs {
		if *keyPair.KeyName == d.Id() {
			d.Set("key_name", keyPair.KeyName)
			d.Set("fingerprint", keyPair.KeyFingerprint)
			return nil
		}
	}

	return fmt.Errorf("Unable to find key pair within: %#v", resp.KeyPairs)
}

func resourceAwsKeyPairDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	_, err := conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{
		KeyName: aws.String(d.Id()),
	})
	return err
}
<commit_msg>fix format<commit_after>package aws

import (
	"fmt"
	"strings"

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
)

func resourceAwsKeyPair() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsKeyPairCreate,
		Read:   resourceAwsKeyPairRead,
		Update: nil,
		Delete: resourceAwsKeyPairDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		SchemaVersion: 1,
		MigrateState:  resourceAwsKeyPairMigrateState,

		Schema: map[string]*schema.Schema{
			"key_name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"key_name_prefix"},
				ValidateFunc:  validateMaxLength(255),
			},
			"key_name_prefix": {
				Type:          schema.TypeString,
				Optional:      true,
				ForceNew:      true,
				ConflictsWith: []string{"key_name"},
				ValidateFunc:  validateMaxLength(255 - resource.UniqueIDSuffixLength),
			},
			"public_key": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				StateFunc: func(v interface{}) string {
					switch v.(type) {
					case string:
						return strings.TrimSpace(v.(string))
					default:
						return ""
					}
				},
			},
			"fingerprint": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsKeyPairCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	var keyName string
	if v, ok := d.GetOk("key_name"); ok {
		keyName = v.(string)
	} else if v, ok := d.GetOk("key_name_prefix"); ok {
		keyName = resource.PrefixedUniqueId(v.(string))
		d.Set("key_name", keyName)
	} else {
		keyName = resource.UniqueId()
		d.Set("key_name", keyName)
	}

	publicKey := d.Get("public_key").(string)
	req := &ec2.ImportKeyPairInput{
		KeyName:           aws.String(keyName),
		PublicKeyMaterial: []byte(publicKey),
	}
	resp, err := conn.ImportKeyPair(req)
	if err != nil {
		return fmt.Errorf("Error import KeyPair: %s", err)
	}

	d.Set("fingerprint", *resp.KeyFingerprint)
	d.SetId(*resp.KeyName)
	return nil
}

func resourceAwsKeyPairRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	req := &ec2.DescribeKeyPairsInput{
		KeyNames: []*string{aws.String(d.Id())},
	}
	resp, err := conn.DescribeKeyPairs(req)
	if err != nil {
		awsErr, ok := err.(awserr.Error)
		if ok && awsErr.Code() == "InvalidKeyPair.NotFound" {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving KeyPair: %s", err)
	}

	for _, keyPair := range resp.KeyPairs {
		if *keyPair.KeyName == d.Id() {
			d.Set("key_name", keyPair.KeyName)
			d.Set("fingerprint", keyPair.KeyFingerprint)
			return nil
		}
	}

	return fmt.Errorf("Unable to find key pair within: %#v", resp.KeyPairs)
}

func resourceAwsKeyPairDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	_, err := conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{
		KeyName: aws.String(d.Id()),
	})
	return err
}
<|endoftext|>


<commit_before>package textmate

import (
	"code.google.com/p/log4go"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/quarnster/parser"
	"io/ioutil"
	"lime/3rdparty/libs/rubex"
	"lime/backend/loaders"
	"strconv"
	"strings"
)

const maxiter = 10000

type (
	Regex struct {
		re        *rubex.Regexp
		lastIndex int
		lastFound int
		lastData  string
	}

	Language struct {
		UnpatchedLanguage
	}

	LanguageProvider map[string]*Language

	UnpatchedLanguage struct {
		FileTypes      []string
		FirstLineMatch string
		RootPattern    RootPattern `json:"patterns"`
		Repository     map[string]*Pattern
		ScopeName      string
	}

	Named struct {
		Name string
	}

	Captures map[string]Named

	MatchObject []int

	Pattern struct {
		Named
		Include        string
		Match          Regex
		Captures       Captures
		Begin          Regex
		BeginCaptures  Captures
		End            Regex
		EndCaptures    Captures
		Patterns       []*Pattern
		owner          *Language // needed for include directives
		cachedData     string
		cachedPat      *Pattern
		cachedPatterns []*Pattern
		cachedMatch    MatchObject
		hits           int
		misses         int
	}
	RootPattern struct {
		Pattern
	}

	LanguageParser struct {
		Language *Language
		root     parser.Node
	}
)

var (
	Provider = make(LanguageProvider)
	failed   = make(map[string]bool)
)

func (t LanguageProvider) GetLanguage(id string) (*Language, error) {
	if v, ok := t[id]; !ok {
		return nil, errors.New("Can't handle id " + id)
	} else {
		return v, nil
	}
}

func (t LanguageProvider) Load(fn string) error {
	if d, err := ioutil.ReadFile(fn); err != nil {
		return fmt.Errorf("Couldn't load file %s: %s", fn, err)
	} else {
		var l Language
		if err := loaders.LoadPlist(d, &l); err != nil {
			return err
		} else {
			t[l.ScopeName] = &l
		}
	}
	return nil
}

func (p Pattern) String() (ret string) {
	ret = fmt.Sprintf(`---------------------------------------
Name:    %s
Match:   %s
Begin:   %s
End:     %s
Include: %s
`, p.Name, p.Match, p.Begin, p.End, p.Include)
	ret += fmt.Sprintf("<Sub-Patterns>\n")
	for i := range p.Patterns {
		inner := fmt.Sprintf("%s", p.Patterns[i])
		ret += fmt.Sprintf("\t%s\n", strings.Replace(strings.Replace(inner, "\t", "\t\t", -1), "\n", "\n\t", -1))
	}
	ret += fmt.Sprintf("</Sub-Patterns>\n---------------------------------------")
	return
}

func (r Regex) String() string {
	if r.re == nil {
		return "nil"
	}
	return fmt.Sprintf("%s   // %d, %d", r.re.String(), r.lastIndex, r.lastFound)
}

func (r *RootPattern) String() (ret string) {
	for i := range r.Patterns {
		ret += fmt.Sprintf("\t%s\n", r.Patterns[i])
	}
	return
}

func (s *Language) String() string {
	return fmt.Sprintf("%s\n%s", s.ScopeName, s.RootPattern)
}

func (p *Pattern) setOwner(l *Language) {
	p.owner = l
	for i := range p.Patterns {
		p.Patterns[i].setOwner(l)
	}
}

func (l *Language) UnmarshalJSON(data []byte) error {
	if err := json.Unmarshal(data, &l.UnpatchedLanguage); err != nil {
		return err
	}
	l.RootPattern.setOwner(l)
	for k := range l.Repository {
		l.Repository[k].setOwner(l)
	}
	return nil
}

func (r *RootPattern) UnmarshalJSON(data []byte) error {
	return json.Unmarshal(data, &r.Patterns)
}

func (r *Regex) UnmarshalJSON(data []byte) error {
	str := string(data[1 : len(data)-1])
	str = strings.Replace(str, "\\\\", "\\", -1)
	str = strings.Replace(str, "\\n", "\n", -1)
	str = strings.Replace(str, "\\t", "\t", -1)
	if re, err := rubex.Compile(str); err != nil {
		log4go.Warn("Couldn't compile language pattern %s: %s", str, err)
	} else {
		r.re = re
	}
	return nil
}

func (m MatchObject) fix(add int) {
	for i := range m {
		if m[i] != -1 {
			m[i] += add
		}
	}
}

func (r *Regex) Find(data string, pos int) MatchObject {
	if r.lastData != data || r.lastIndex > pos {
		r.lastData = data
		r.lastFound = 0
	}
	r.lastIndex = pos
	for r.lastFound < len(data) {
		ret := r.re.FindStringSubmatchIndex(data[r.lastFound:])
		if ret == nil {
			break
		} else if (ret[0] + r.lastFound) < pos {
			if ret[0] == 0 {
				r.lastFound++
			} else {
				r.lastFound += ret[0]
			}
			continue
		}
		mo := MatchObject(ret)
		mo.fix(r.lastFound)
		return mo
	}
	return nil
}

func (p *Pattern) FirstMatch(data string, pos int) (pat *Pattern, ret MatchObject) {
	startIdx := -1
	for i := 0; i < len(p.cachedPatterns); {
		ip, im := p.cachedPatterns[i].Cache(data, pos)
		if im != nil && im[0] != im[1] {
			if startIdx < 0 || startIdx > im[0] {
				startIdx, pat, ret = im[0], ip, im
				// This match is right at the start, we're not going to find a better pattern than this,
				// so stop the search
				if im[0] == pos {
					break
				}
			}
			i++
		} else {
			// If it wasn't found now, it'll never be found, so the pattern can be popped from the cache
			copy(p.cachedPatterns[i:], p.cachedPatterns[i+1:])
			p.cachedPatterns = p.cachedPatterns[:len(p.cachedPatterns)-1]
		}
	}
	return
}

func (p *Pattern) Cache(data string, pos int) (pat *Pattern, ret MatchObject) {
	if p.cachedData == data {
		if p.cachedMatch == nil {
			return nil, nil
		}
		if p.cachedMatch[0] >= pos {
			p.hits++
			return p.cachedPat, p.cachedMatch
		}
	} else {
		p.cachedPatterns = nil
	}
	if p.cachedPatterns == nil {
		p.cachedPatterns = make([]*Pattern, len(p.Patterns))
		copy(p.cachedPatterns, p.Patterns)
	}
	p.misses++

	if p.Match.re != nil {
		pat, ret = p, p.Match.Find(data, pos)
	} else if p.Begin.re != nil {
		pat, ret = p, p.Begin.Find(data, pos)
	} else if p.Include != "" {
		if z := p.Include[0]; z == '#' {
			key := p.Include[1:]
			if p2, ok := p.owner.Repository[key]; ok {
				pat, ret = p2.Cache(data, pos)
			} else {
				log4go.Warn("Not found in repository: %s", p.Include)
			}
		} else if z == '$' {
			// TODO(q): Implement tmLanguage $ include directives
			log4go.Warn("Unhandled include directive: %s", p.Include)
		} else if l, err := Provider.GetLanguage(p.Include); err != nil {
			if !failed[p.Include] {
				log4go.Warn("Include directive %s failed: %s", p.Include, err)
			}
			failed[p.Include] = true
		} else {
			return l.RootPattern.Cache(data, pos)
		}
	} else {
		pat, ret = p.FirstMatch(data, pos)
	}
	p.cachedData = data
	p.cachedMatch = ret
	p.cachedPat = pat

	return
}

func (p *Pattern) CreateCaptureNodes(data string, pos int, d parser.DataSource, mo MatchObject, parent *parser.Node, cap Captures) {
	ranges := make([]parser.Range, len(mo)/2)
	parentIndex := make([]int, len(ranges))
	parents := make([]*parser.Node, len(parentIndex))
	for i := range ranges {
		ranges[i] = parser.Range{mo[i*2+0], mo[i*2+1]}
		if i < 2 {
			parents[i] = parent
			continue
		}
		r := ranges[i]
		for j := i - 1; j >= 0; j-- {
			if ranges[j].Contains(r) {
				parentIndex[i] = j
				break
			}
		}
	}

	for k, v := range cap {
		i64, err := strconv.ParseInt(k, 10, 32)
		if i := int(i64); err == nil && i < len(parents) {
			if ranges[i].Start == -1 {
				continue
			}
			child := &parser.Node{Name: v.Name, Range: ranges[i], P: d}
			parents[i] = child
			if i == 0 {
				parent.Append(child)
				continue
			}
			var p *parser.Node
			for p == nil {
				i = parentIndex[i]
				p = parents[i]
			}
			p.Append(child)
		}
	}
}

func (p *Pattern) CreateNode(data string, pos int, d parser.DataSource, mo MatchObject) *parser.Node {
	ret := parser.Node{Name: p.Name, Range: parser.Range{mo[0], mo[1]}, P: d}
	if p.Match.re != nil {
		p.CreateCaptureNodes(data, pos, d, mo, &ret, p.Captures)
	} else if p.Begin.re != nil {
		if len(p.BeginCaptures) > 0 {
			p.CreateCaptureNodes(data, pos, d, mo, &ret, p.BeginCaptures)
		} else {
			p.CreateCaptureNodes(data, pos, d, mo, &ret, p.Captures)
		}

		if p.End.re != nil {
			var (
				found  = false
				i, end int
			)
			for i, end = ret.Range.End, len(data); i < len(data); {
				endmatch := p.End.Find(data, i)
				if endmatch != nil {
					end = endmatch[1]
				} else {
					if !found {
						// oops.. no end found at all, set it to the next line
						if e2 := strings.IndexRune(data[i:], '\n'); e2 != -1 {
							end = i + e2
						}
						break
					} else {
						end = i
						break
					}
				}
				if (endmatch == nil || (endmatch != nil && endmatch[0] != i)) && len(p.cachedPatterns) > 0 {
					// Might be more recursive patterns to apply BEFORE the end is reached
					pattern2, match2 := p.FirstMatch(data, i)
					if match2 != nil &&
						((endmatch == nil && match2[0] < end) ||
							(endmatch != nil && match2[0] < endmatch[0])) {

						found = true
						r := pattern2.CreateNode(data, i, d, match2)
						ret.Append(r)
						i = r.Range.End
						continue
					}
				}
				if endmatch != nil {
					if len(p.EndCaptures) > 0 {
						p.CreateCaptureNodes(data, i, d, endmatch, &ret, p.EndCaptures)
					} else {
						p.CreateCaptureNodes(data, i, d, endmatch, &ret, p.Captures)
					}
				}
				break
			}
			ret.Range.End = end
		}
	}
	ret.UpdateRange()
	return &ret
}

type dp struct {
	data []rune
}

func (d *dp) Data(a, b int) string {
	return string(d.data[a:b])
}

func (lp *LanguageParser) RootNode() *parser.Node {
	return &lp.root
}

func (lp *LanguageParser) patch(lut []int, node *parser.Node) {
	node.Range.Start = lut[node.Range.Start]
	node.Range.End = lut[node.Range.End]
	for _, child := range node.Children {
		lp.patch(lut, child)
	}
}

func (lp *LanguageParser) Parse(data string) bool {
	d := &dp{[]rune(data)}
	lp.root = parser.Node{P: d, Name: lp.Language.ScopeName}
	iter := maxiter
	for i := 0; i < len(data) && iter > 0; iter-- {
		pat, ret := lp.Language.RootPattern.Cache(data, i)
		nl := strings.IndexAny(data[i:], "\n\r")

		if nl != -1 {
			nl += i
		}
		if ret == nil {
			break
		} else if nl > 0 && nl <= ret[0] {
			i = nl
			for i < len(data) && (data[i] == '\n' || data[i] == '\r') {
				i++
			}
		} else {
			n := pat.CreateNode(data, i, d, ret)
			lp.root.Append(n)

			i = n.Range.End
		}
	}
	lp.root.UpdateRange()
	lut := make([]int, len(data))
	j := 0
	for i := range data {
		lut[i] = j
		j++
	}
	lp.patch(lut, &lp.root)
	return true
}
<commit_msg>Don't patch empty data.<commit_after>package textmate

import (
	"code.google.com/p/log4go"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/quarnster/parser"
	"io/ioutil"
	"lime/3rdparty/libs/rubex"
	"lime/backend/loaders"
	"strconv"
	"strings"
)

const maxiter = 10000

type (
	Regex struct {
		re        *rubex.Regexp
		lastIndex int
		lastFound int
		lastData  string
	}

	Language struct {
		UnpatchedLanguage
	}

	LanguageProvider map[string]*Language

	UnpatchedLanguage struct {
		FileTypes      []string
		FirstLineMatch string
		RootPattern    RootPattern `json:"patterns"`
		Repository     map[string]*Pattern
		ScopeName      string
	}

	Named struct {
		Name string
	}

	Captures map[string]Named

	MatchObject []int

	Pattern struct {
		Named
		Include        string
		Match          Regex
		Captures       Captures
		Begin          Regex
		BeginCaptures  Captures
		End            Regex
		EndCaptures    Captures
		Patterns       []*Pattern
		owner          *Language // needed for include directives
		cachedData     string
		cachedPat      *Pattern
		cachedPatterns []*Pattern
		cachedMatch    MatchObject
		hits           int
		misses         int
	}
	RootPattern struct {
		Pattern
	}

	LanguageParser struct {
		Language *Language
		root     parser.Node
	}
)

var (
	Provider = make(LanguageProvider)
	failed   = make(map[string]bool)
)

func (t LanguageProvider) GetLanguage(id string) (*Language, error) {
	if v, ok := t[id]; !ok {
		return nil, errors.New("Can't handle id " + id)
	} else {
		return v, nil
	}
}

func (t LanguageProvider) Load(fn string) error {
	if d, err := ioutil.ReadFile(fn); err != nil {
		return fmt.Errorf("Couldn't load file %s: %s", fn, err)
	} else {
		var l Language
		if err := loaders.LoadPlist(d, &l); err != nil {
			return err
		} else {
			t[l.ScopeName] = &l
		}
	}
	return nil
}

func (p Pattern) String() (ret string) {
	ret = fmt.Sprintf(`---------------------------------------
Name:    %s
Match:   %s
Begin:   %s
End:     %s
Include: %s
`, p.Name, p.Match, p.Begin, p.End, p.Include)
	ret += fmt.Sprintf("<Sub-Patterns>\n")
	for i := range p.Patterns {
		inner := fmt.Sprintf("%s", p.Patterns[i])
		ret += fmt.Sprintf("\t%s\n", strings.Replace(strings.Replace(inner, "\t", "\t\t", -1), "\n", "\n\t", -1))
	}
	ret += fmt.Sprintf("</Sub-Patterns>\n---------------------------------------")
	return
}

func (r Regex) String() string {
	if r.re == nil {
		return "nil"
	}
	return fmt.Sprintf("%s   // %d, %d", r.re.String(), r.lastIndex, r.lastFound)
}

func (r *RootPattern) String() (ret string) {
	for i := range r.Patterns {
		ret += fmt.Sprintf("\t%s\n", r.Patterns[i])
	}
	return
}

func (s *Language) String() string {
	return fmt.Sprintf("%s\n%s", s.ScopeName, s.RootPattern)
}

func (p *Pattern) setOwner(l *Language) {
	p.owner = l
	for i := range p.Patterns {
		p.Patterns[i].setOwner(l)
	}
}

func (l *Language) UnmarshalJSON(data []byte) error {
	if err := json.Unmarshal(data, &l.UnpatchedLanguage); err != nil {
		return err
	}
	l.RootPattern.setOwner(l)
	for k := range l.Repository {
		l.Repository[k].setOwner(l)
	}
	return nil
}

func (r *RootPattern) UnmarshalJSON(data []byte) error {
	return json.Unmarshal(data, &r.Patterns)
}

func (r *Regex) UnmarshalJSON(data []byte) error {
	str := string(data[1 : len(data)-1])
	str = strings.Replace(str, "\\\\", "\\", -1)
	str = strings.Replace(str, "\\n", "\n", -1)
	str = strings.Replace(str, "\\t", "\t", -1)
	if re, err := rubex.Compile(str); err != nil {
		log4go.Warn("Couldn't compile language pattern %s: %s", str, err)
	} else {
		r.re = re
	}
	return nil
}

func (m MatchObject) fix(add int) {
	for i := range m {
		if m[i] != -1 {
			m[i] += add
		}
	}
}

func (r *Regex) Find(data string, pos int) MatchObject {
	if r.lastData != data || r.lastIndex > pos {
		r.lastData = data
		r.lastFound = 0
	}
	r.lastIndex = pos
	for r.lastFound < len(data) {
		ret := r.re.FindStringSubmatchIndex(data[r.lastFound:])
		if ret == nil {
			break
		} else if (ret[0] + r.lastFound) < pos {
			if ret[0] == 0 {
				r.lastFound++
			} else {
				r.lastFound += ret[0]
			}
			continue
		}
		mo := MatchObject(ret)
		mo.fix(r.lastFound)
		return mo
	}
	return nil
}

func (p *Pattern) FirstMatch(data string, pos int) (pat *Pattern, ret MatchObject) {
	startIdx := -1
	for i := 0; i < len(p.cachedPatterns); {
		ip, im := p.cachedPatterns[i].Cache(data, pos)
		if im != nil && im[0] != im[1] {
			if startIdx < 0 || startIdx > im[0] {
				startIdx, pat, ret = im[0], ip, im
				// This match is right at the start, we're not going to find a better pattern than this,
				// so stop the search
				if im[0] == pos {
					break
				}
			}
			i++
		} else {
			// If it wasn't found now, it'll never be found, so the pattern can be popped from the cache
			copy(p.cachedPatterns[i:], p.cachedPatterns[i+1:])
			p.cachedPatterns = p.cachedPatterns[:len(p.cachedPatterns)-1]
		}
	}
	return
}

func (p *Pattern) Cache(data string, pos int) (pat *Pattern, ret MatchObject) {
	if p.cachedData == data {
		if p.cachedMatch == nil {
			return nil, nil
		}
		if p.cachedMatch[0] >= pos {
			p.hits++
			return p.cachedPat, p.cachedMatch
		}
	} else {
		p.cachedPatterns = nil
	}
	if p.cachedPatterns == nil {
		p.cachedPatterns = make([]*Pattern, len(p.Patterns))
		copy(p.cachedPatterns, p.Patterns)
	}
	p.misses++

	if p.Match.re != nil {
		pat, ret = p, p.Match.Find(data, pos)
	} else if p.Begin.re != nil {
		pat, ret = p, p.Begin.Find(data, pos)
	} else if p.Include != "" {
		if z := p.Include[0]; z == '#' {
			key := p.Include[1:]
			if p2, ok := p.owner.Repository[key]; ok {
				pat, ret = p2.Cache(data, pos)
			} else {
				log4go.Warn("Not found in repository: %s", p.Include)
			}
		} else if z == '$' {
			// TODO(q): Implement tmLanguage $ include directives
			log4go.Warn("Unhandled include directive: %s", p.Include)
		} else if l, err := Provider.GetLanguage(p.Include); err != nil {
			if !failed[p.Include] {
				log4go.Warn("Include directive %s failed: %s", p.Include, err)
			}
			failed[p.Include] = true
		} else {
			return l.RootPattern.Cache(data, pos)
		}
	} else {
		pat, ret = p.FirstMatch(data, pos)
	}
	p.cachedData = data
	p.cachedMatch = ret
	p.cachedPat = pat

	return
}

func (p *Pattern) CreateCaptureNodes(data string, pos int, d parser.DataSource, mo MatchObject, parent *parser.Node, cap Captures) {
	ranges := make([]parser.Range, len(mo)/2)
	parentIndex := make([]int, len(ranges))
	parents := make([]*parser.Node, len(parentIndex))
	for i := range ranges {
		ranges[i] = parser.Range{mo[i*2+0], mo[i*2+1]}
		if i < 2 {
			parents[i] = parent
			continue
		}
		r := ranges[i]
		for j := i - 1; j >= 0; j-- {
			if ranges[j].Contains(r) {
				parentIndex[i] = j
				break
			}
		}
	}

	for k, v := range cap {
		i64, err := strconv.ParseInt(k, 10, 32)
		if i := int(i64); err == nil && i < len(parents) {
			if ranges[i].Start == -1 {
				continue
			}
			child := &parser.Node{Name: v.Name, Range: ranges[i], P: d}
			parents[i] = child
			if i == 0 {
				parent.Append(child)
				continue
			}
			var p *parser.Node
			for p == nil {
				i = parentIndex[i]
				p = parents[i]
			}
			p.Append(child)
		}
	}
}

func (p *Pattern) CreateNode(data string, pos int, d parser.DataSource, mo MatchObject) *parser.Node {
	ret := parser.Node{Name: p.Name, Range: parser.Range{mo[0], mo[1]}, P: d}
	if p.Match.re != nil {
		p.CreateCaptureNodes(data, pos, d, mo, &ret, p.Captures)
	} else if p.Begin.re != nil {
		if len(p.BeginCaptures) > 0 {
			p.CreateCaptureNodes(data, pos, d, mo, &ret, p.BeginCaptures)
		} else {
			p.CreateCaptureNodes(data, pos, d, mo, &ret, p.Captures)
		}

		if p.End.re != nil {
			var (
				found  = false
				i, end int
			)
			for i, end = ret.Range.End, len(data); i < len(data); {
				endmatch := p.End.Find(data, i)
				if endmatch != nil {
					end = endmatch[1]
				} else {
					if !found {
						// oops.. no end found at all, set it to the next line
						if e2 := strings.IndexRune(data[i:], '\n'); e2 != -1 {
							end = i + e2
						}
						break
					} else {
						end = i
						break
					}
				}
				if (endmatch == nil || (endmatch != nil && endmatch[0] != i)) && len(p.cachedPatterns) > 0 {
					// Might be more recursive patterns to apply BEFORE the end is reached
					pattern2, match2 := p.FirstMatch(data, i)
					if match2 != nil &&
						((endmatch == nil && match2[0] < end) ||
							(endmatch != nil && match2[0] < endmatch[0])) {

						found = true
						r := pattern2.CreateNode(data, i, d, match2)
						ret.Append(r)
						i = r.Range.End
						continue
					}
				}
				if endmatch != nil {
					if len(p.EndCaptures) > 0 {
						p.CreateCaptureNodes(data, i, d, endmatch, &ret, p.EndCaptures)
					} else {
						p.CreateCaptureNodes(data, i, d, endmatch, &ret, p.Captures)
					}
				}
				break
			}
			ret.Range.End = end
		}
	}
	ret.UpdateRange()
	return &ret
}

type dp struct {
	data []rune
}

func (d *dp) Data(a, b int) string {
	return string(d.data[a:b])
}

func (lp *LanguageParser) RootNode() *parser.Node {
	return &lp.root
}

func (lp *LanguageParser) patch(lut []int, node *parser.Node) {
	node.Range.Start = lut[node.Range.Start]
	node.Range.End = lut[node.Range.End]
	for _, child := range node.Children {
		lp.patch(lut, child)
	}
}

func (lp *LanguageParser) Parse(data string) bool {
	d := &dp{[]rune(data)}
	lp.root = parser.Node{P: d, Name: lp.Language.ScopeName}
	iter := maxiter
	for i := 0; i < len(data) && iter > 0; iter-- {
		pat, ret := lp.Language.RootPattern.Cache(data, i)
		nl := strings.IndexAny(data[i:], "\n\r")

		if nl != -1 {
			nl += i
		}
		if ret == nil {
			break
		} else if nl > 0 && nl <= ret[0] {
			i = nl
			for i < len(data) && (data[i] == '\n' || data[i] == '\r') {
				i++
			}
		} else {
			n := pat.CreateNode(data, i, d, ret)
			lp.root.Append(n)

			i = n.Range.End
		}
	}
	lp.root.UpdateRange()
	if len(data) != 0 {
		lut := make([]int, len(data))
		j := 0
		for i := range data {
			lut[i] = j
			j++
		}
		lp.patch(lut, &lp.root)
	}
	return true
}
<|endoftext|>


<commit_before>package net

import (
	"context"
	"math/rand"
	"net"
	"sync"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var (
	serverList []string
)

type Resolver struct {
	serverList []string
	mutex      sync.Mutex
}

func NewResolver(list []string) *net.Resolver {
	var r net.Resolver
	r.PreferGo = true
	r.Dial = dialer
	return &r
}

func UpdateResolvList(list []string) {
	serverList = list
}

func OverrideDefaultResolver(list []string) {
	var r net.Resolver
	r.PreferGo = true
	r.Dial = dialer
	net.DefaultResolver = &r
}

func dialer(ctx context.Context, network, address string) (net.Conn, error) {
	d := net.Dialer{}
	list := serverList

	count := len(list)
	id := rand.Intn(count)
	net, err := d.DialContext(ctx, "udp", list[id])
	if err == nil {
		return net, err
	}
	//skip last
	for i := 0; i+1 < count; i++ {
		id++
		id = id % count
		net, err = d.DialContext(ctx, "udp", list[id])
		if err == nil {
			return net, err
		}
	}
	return net, err
}
<commit_msg>fix build<commit_after>package net

import (
	"context"
	"math/rand"
	stdnet "net"
	"sync"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var (
	serverList []string
)

type Resolver struct {
	serverList []string
	mutex      sync.Mutex
}

func NewResolver(list []string) *stdnet.Resolver {
	var r stdnet.Resolver
	r.PreferGo = true
	r.Dial = dialer
	return &r
}

func UpdateResolvList(list []string) {
	serverList = list
}

func OverrideDefaultResolver(list []string) {
	var r stdnet.Resolver
	r.PreferGo = true
	r.Dial = dialer
	stdnet.DefaultResolver = &r
}

func dialer(ctx context.Context, network, address string) (stdnet.Conn, error) {
	d := stdnet.Dialer{}
	list := serverList

	count := len(list)
	id := rand.Intn(count)
	conn, err := d.DialContext(ctx, "udp", list[id])
	if err == nil {
		return conn, err
	}
	//skip last
	for i := 0; i+1 < count; i++ {
		id++
		id = id % count
		conn, err = d.DialContext(ctx, "udp", list[id])
		if err == nil {
			return conn, err
		}
	}
	return conn, err
}
<|endoftext|>


<commit_before>package controller

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/oinume/lekcije/server/config"
	"github.com/oinume/lekcije/server/context_data"
	"github.com/oinume/lekcije/server/errors"
)

var _ = fmt.Print

func Static(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, r.URL.Path[1:])
}

func Index(w http.ResponseWriter, r *http.Request) {
	if _, err := context_data.GetLoggedInUser(r.Context()); err == nil {
		http.Redirect(w, r, "/me", http.StatusFound)
	} else {
		indexLogout(w, r)
	}
}

func indexLogout(w http.ResponseWriter, r *http.Request) {
	t := ParseHTMLTemplates(TemplatePath("index.html"))
	type Data struct {
		commonTemplateData
	}
	data := &Data{
		commonTemplateData: getCommonTemplateData(r, false, 0),
	}

	if err := t.Execute(w, data); err != nil {
		InternalServerError(w, errors.InternalWrapf(err, "Failed to template.Execute()"))
		return
	}
}

func Signup(w http.ResponseWriter, r *http.Request) {
	if _, err := context_data.GetLoggedInUser(r.Context()); err == nil {
		http.Redirect(w, r, "/me", http.StatusFound)
		return
	}

	t := ParseHTMLTemplates(TemplatePath("signup.html"))
	data := struct {
		commonTemplateData
	}{
		commonTemplateData: getCommonTemplateData(r, false, 0),
	}
	if err := t.Execute(w, &data); err != nil {
		InternalServerError(w, errors.InternalWrapf(err, "Failed to template.Execute()"))
		return
	}
}

func RobotsTxt(w http.ResponseWriter, r *http.Request) {
	content := fmt.Sprintf(`
User-agent: *
Allow: /
Sitemap: %s/sitemap.xml
`, config.WebURL())
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	fmt.Fprintln(w, strings.TrimSpace(content))
}

func SitemapXML(w http.ResponseWriter, r *http.Request) {
	content := fmt.Sprintf(`
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>%s/</loc>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>%s/terms</loc>
    <priority>1.0</priority>
  </url>
</urlset>
	`, config.WebURL(), config.WebURL())
	w.Header().Set("Content-Type", "text/xml; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	fmt.Fprintln(w, strings.TrimSpace(content))
}

func Terms(w http.ResponseWriter, r *http.Request) {
	t := ParseHTMLTemplates(TemplatePath("terms.html"))
	type Data struct {
		commonTemplateData
	}

	userID := uint32(0)
	if user, err := context_data.GetLoggedInUser(r.Context()); err == nil {
		userID = user.ID
	}
	data := &Data{
		commonTemplateData: getCommonTemplateData(r, false, userID),
	}

	if err := t.Execute(w, data); err != nil {
		InternalServerError(w, errors.InternalWrapf(err, "Failed to template.Execute()"))
		return
	}
}
<commit_msg>Add /signup<commit_after>package controller

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/oinume/lekcije/server/config"
	"github.com/oinume/lekcije/server/context_data"
	"github.com/oinume/lekcije/server/errors"
)

var _ = fmt.Print

func Static(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, r.URL.Path[1:])
}

func Index(w http.ResponseWriter, r *http.Request) {
	if _, err := context_data.GetLoggedInUser(r.Context()); err == nil {
		http.Redirect(w, r, "/me", http.StatusFound)
	} else {
		indexLogout(w, r)
	}
}

func indexLogout(w http.ResponseWriter, r *http.Request) {
	t := ParseHTMLTemplates(TemplatePath("index.html"))
	type Data struct {
		commonTemplateData
	}
	data := &Data{
		commonTemplateData: getCommonTemplateData(r, false, 0),
	}

	if err := t.Execute(w, data); err != nil {
		InternalServerError(w, errors.InternalWrapf(err, "Failed to template.Execute()"))
		return
	}
}

func Signup(w http.ResponseWriter, r *http.Request) {
	if _, err := context_data.GetLoggedInUser(r.Context()); err == nil {
		http.Redirect(w, r, "/me", http.StatusFound)
		return
	}

	t := ParseHTMLTemplates(TemplatePath("signup.html"))
	data := struct {
		commonTemplateData
	}{
		commonTemplateData: getCommonTemplateData(r, false, 0),
	}
	if err := t.Execute(w, &data); err != nil {
		InternalServerError(w, errors.InternalWrapf(err, "Failed to template.Execute()"))
		return
	}
}

func RobotsTxt(w http.ResponseWriter, r *http.Request) {
	content := fmt.Sprintf(`
User-agent: *
Allow: /
Sitemap: %s/sitemap.xml
`, config.WebURL())
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	fmt.Fprintln(w, strings.TrimSpace(content))
}

func SitemapXML(w http.ResponseWriter, r *http.Request) {
	// TODO: Move to an external file
	content := fmt.Sprintf(`
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>%s/</loc>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>%s/signup</loc>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>%s/terms</loc>
    <priority>1.0</priority>
  </url>
</urlset>
	`, config.WebURL(), config.WebURL(), config.WebURL())
	w.Header().Set("Content-Type", "text/xml; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	fmt.Fprintln(w, strings.TrimSpace(content))
}

func Terms(w http.ResponseWriter, r *http.Request) {
	t := ParseHTMLTemplates(TemplatePath("terms.html"))
	type Data struct {
		commonTemplateData
	}

	userID := uint32(0)
	if user, err := context_data.GetLoggedInUser(r.Context()); err == nil {
		userID = user.ID
	}
	data := &Data{
		commonTemplateData: getCommonTemplateData(r, false, userID),
	}

	if err := t.Execute(w, data); err != nil {
		InternalServerError(w, errors.InternalWrapf(err, "Failed to template.Execute()"))
		return
	}
}
<|endoftext|>


<commit_before>// +build darwin

package host

import (
	"bytes"
	"context"
	"encoding/binary"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/shirou/gopsutil/internal/common"
	"github.com/shirou/gopsutil/process"
	"golang.org/x/sys/unix"
)

// from utmpx.h
const USER_PROCESS = 7

func Info() (*InfoStat, error) {
	return InfoWithContext(context.Background())
}

func InfoWithContext(ctx context.Context) (*InfoStat, error) {
	ret := &InfoStat{
		OS:             runtime.GOOS,
		PlatformFamily: "darwin",
	}

	hostname, err := os.Hostname()
	if err == nil {
		ret.Hostname = hostname
	}

	kernelVersion, err := KernelVersionWithContext(ctx)
	if err == nil {
		ret.KernelVersion = kernelVersion
	}

	platform, family, pver, err := PlatformInformation()
	if err == nil {
		ret.Platform = platform
		ret.PlatformFamily = family
		ret.PlatformVersion = pver
	}

	system, role, err := Virtualization()
	if err == nil {
		ret.VirtualizationSystem = system
		ret.VirtualizationRole = role
	}

	boot, err := BootTime()
	if err == nil {
		ret.BootTime = boot
		ret.Uptime = uptime(boot)
	}

	procs, err := process.Pids()
	if err == nil {
		ret.Procs = uint64(len(procs))
	}

	uuid, err := unix.Sysctl("kern.uuid")
	if err == nil && uuid != "" {
		ret.HostID = strings.ToLower(uuid)
	}

	return ret, nil
}

// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64

func BootTime() (uint64, error) {
	return BootTimeWithContext(context.Background())
}

func BootTimeWithContext(ctx context.Context) (uint64, error) {
	// https://github.com/AaronO/dashd/blob/222e32ef9f7a1f9bea4a8da2c3627c4cb992f860/probe/probe_darwin.go
	t := atomic.LoadUint64(&cachedBootTime)
	if t != 0 {
		return t, nil
	}
	value, err := unix.Sysctl("kern.boottime")
	if err != nil {
		return 0, err
	}
	bytes := []byte(value[:])
	var boottime uint64
	boottime = uint64(bytes[0]) + uint64(bytes[1])*256 + uint64(bytes[2])*256*256 + uint64(bytes[3])*256*256*256

	atomic.StoreUint64(&cachedBootTime, boottime)

	return boottime, nil
}

func uptime(boot uint64) uint64 {
	return uint64(time.Now().Unix()) - boot
}

func Uptime() (uint64, error) {
	return UptimeWithContext(context.Background())
}

func UptimeWithContext(ctx context.Context) (uint64, error) {
	boot, err := BootTimeWithContext(ctx)
	if err != nil {
		return 0, err
	}
	return uptime(boot), nil
}

func Users() ([]UserStat, error) {
	return UsersWithContext(context.Background())
}

func UsersWithContext(ctx context.Context) ([]UserStat, error) {
	utmpfile := "/var/run/utmpx"
	var ret []UserStat

	file, err := os.Open(utmpfile)
	if err != nil {
		return ret, err
	}
	defer file.Close()

	buf, err := ioutil.ReadAll(file)
	if err != nil {
		return ret, err
	}

	u := Utmpx{}
	entrySize := int(unsafe.Sizeof(u))
	count := len(buf) / entrySize

	for i := 0; i < count; i++ {
		b := buf[i*entrySize : i*entrySize+entrySize]

		var u Utmpx
		br := bytes.NewReader(b)
		err := binary.Read(br, binary.LittleEndian, &u)
		if err != nil {
			continue
		}
		if u.Type != USER_PROCESS {
			continue
		}
		user := UserStat{
			User:     common.IntToString(u.User[:]),
			Terminal: common.IntToString(u.Line[:]),
			Host:     common.IntToString(u.Host[:]),
			Started:  int(u.Tv.Sec),
		}
		ret = append(ret, user)
	}

	return ret, nil

}

func PlatformInformation() (string, string, string, error) {
	return PlatformInformationWithContext(context.Background())
}

func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
	platform := ""
	family := ""
	pver := ""

	sw_vers, err := exec.LookPath("sw_vers")
	if err != nil {
		return "", "", "", err
	}

	p, err := unix.Sysctl("kern.ostype")
	if err == nil {
		platform = strings.ToLower(p)
	}

	out, err := invoke.CommandWithContext(ctx, sw_vers, "-productVersion")
	if err == nil {
		pver = strings.ToLower(strings.TrimSpace(string(out)))
	}

	return platform, family, pver, nil
}

func Virtualization() (string, string, error) {
	return VirtualizationWithContext(context.Background())
}

func VirtualizationWithContext(ctx context.Context) (string, string, error) {
	return "", "", common.ErrNotImplementedError
}

func KernelVersion() (string, error) {
	return KernelVersionWithContext(context.Background())
}

func KernelVersionWithContext(ctx context.Context) (string, error) {
	version, err := unix.Sysctl("kern.osrelease")
	return strings.ToLower(version), err
}

func SensorsTemperatures() ([]TemperatureStat, error) {
	return SensorsTemperaturesWithContext(context.Background())
}

func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
	return []TemperatureStat{}, common.ErrNotImplementedError
}
<commit_msg>Update host_darwin.go<commit_after>// +build darwin

package host

import (
	"bytes"
	"context"
	"encoding/binary"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/shirou/gopsutil/internal/common"
	"github.com/shirou/gopsutil/process"
	"golang.org/x/sys/unix"
)

// from utmpx.h
const USER_PROCESS = 7

func Info() (*InfoStat, error) {
	return InfoWithContext(context.Background())
}

func InfoWithContext(ctx context.Context) (*InfoStat, error) {
	ret := &InfoStat{
		OS:             runtime.GOOS,
		PlatformFamily: "darwin",
	}

	hostname, err := os.Hostname()
	if err == nil {
		ret.Hostname = hostname
	}

	kernelVersion, err := KernelVersionWithContext(ctx)
	if err == nil {
		ret.KernelVersion = kernelVersion
	}

	platform, family, pver, err := PlatformInformation()
	if err == nil {
		ret.Platform = platform
		ret.PlatformFamily = family
		ret.PlatformVersion = pver
	}

	system, role, err := Virtualization()
	if err == nil {
		ret.VirtualizationSystem = system
		ret.VirtualizationRole = role
	}

	boot, err := BootTime()
	if err == nil {
		ret.BootTime = boot
		ret.Uptime = uptime(boot)
	}

	procs, err := process.Pids()
	if err == nil {
		ret.Procs = uint64(len(procs))
	}

	uuid, err := unix.Sysctl("kern.uuid")
	if err == nil && uuid != "" {
		ret.HostID = strings.ToLower(uuid)
	}

	return ret, nil
}

// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64

func BootTime() (uint64, error) {
	return BootTimeWithContext(context.Background())
}

func BootTimeWithContext(ctx context.Context) (uint64, error) {
	// https://github.com/AaronO/dashd/blob/222e32ef9f7a1f9bea4a8da2c3627c4cb992f860/probe/probe_darwin.go
	t := atomic.LoadUint64(&cachedBootTime)
	if t != 0 {
		return t, nil
	}
	value, err := unix.Sysctl("kern.boottime")
	if err != nil {
		return 0, err
	}
	bytes := []byte(value[:])
	var boottime uint64
	boottime = uint64(bytes[0]) + uint64(bytes[1])*256 + uint64(bytes[2])*256*256 + uint64(bytes[3])*256*256*256

	atomic.StoreUint64(&cachedBootTime, boottime)

	return boottime, nil
}

func uptime(boot uint64) uint64 {
	return uint64(time.Now().Unix()) - boot
}

func Uptime() (uint64, error) {
	return UptimeWithContext(context.Background())
}

func UptimeWithContext(ctx context.Context) (uint64, error) {
	boot, err := BootTimeWithContext(ctx)
	if err != nil {
		return 0, err
	}
	return uptime(boot), nil
}

func Users() ([]UserStat, error) {
	return UsersWithContext(context.Background())
}

func UsersWithContext(ctx context.Context) ([]UserStat, error) {
	utmpfile := "/var/run/utmpx"
	var ret []UserStat

	file, err := os.Open(utmpfile)
	if err != nil {
		return ret, err
	}
	defer file.Close()

	buf, err := ioutil.ReadAll(file)
	if err != nil {
		return ret, err
	}

	u := Utmpx{}
	entrySize := int(unsafe.Sizeof(u))
	count := len(buf) / entrySize

	for i := 0; i < count; i++ {
		b := buf[i*entrySize : i*entrySize+entrySize]

		var u Utmpx
		br := bytes.NewReader(b)
		err := binary.Read(br, binary.LittleEndian, &u)
		if err != nil {
			continue
		}
		if u.Type != USER_PROCESS {
			continue
		}
		user := UserStat{
			User:     common.IntToString(u.User[:]),
			Terminal: common.IntToString(u.Line[:]),
			Host:     common.IntToString(u.Host[:]),
			Started:  int(u.Tv.Sec),
		}
		ret = append(ret, user)
	}

	return ret, nil

}

func PlatformInformation() (string, string, string, error) {
	return PlatformInformationWithContext(context.Background())
}

func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
	platform := ""
	family := ""
	pver := ""

	sw_vers, err := exec.LookPath("sw_vers")
	if err != nil {
		return "", "", "", err
	}

	p, err := unix.Sysctl("kern.ostype")
	if err == nil {
		platform = strings.ToLower(p)
	}

	out, err := invoke.CommandWithContext(ctx, sw_vers, "-productVersion")
	if err == nil {
		pver = strings.ToLower(strings.TrimSpace(string(out)))
	}

	// check if the macos server version file exists
	_, err := os.Stat("/System/Library/CoreServices/ServerVersion.plist")

	// server file doesn't exist
	if os.IsNotExist(err) {
		family = "Standalone Workstation"
	} else {
		family = "Server"
	}

	return platform, family, pver, nil
}

func Virtualization() (string, string, error) {
	return VirtualizationWithContext(context.Background())
}

func VirtualizationWithContext(ctx context.Context) (string, string, error) {
	return "", "", common.ErrNotImplementedError
}

func KernelVersion() (string, error) {
	return KernelVersionWithContext(context.Background())
}

func KernelVersionWithContext(ctx context.Context) (string, error) {
	version, err := unix.Sysctl("kern.osrelease")
	return strings.ToLower(version), err
}

func SensorsTemperatures() ([]TemperatureStat, error) {
	return SensorsTemperaturesWithContext(context.Background())
}

func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
	return []TemperatureStat{}, common.ErrNotImplementedError
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"strconv"
	"strings"

	"github.com/gorilla/mux"
)

type callbackManagerData struct {
	Url       string   `json:"url"`
	GroupName string   `json:"group"`
	Topics    []string `json:"topics"`
}

type topicPartitionsData struct {
	Url        string  `json:"url"`
	GroupName  string  `json:"group"`
	Topic      string  `json:"topic"`
	Partitions []int32 `json:"partitions"`
}

type partitionManagerData struct {
	Url               string      `json:"url"`
	GroupName         string      `json:"group"`
	Topic             string      `json:"topic"`
	Partition         int32       `json:"partition"`
	PartitionConsumer interface{} `json:"partition_consumer"`
	Arbiter           interface{} `json:"arbiter"`
	Transporter       interface{} `json:"transporter"`
}

func findCallbackManagerByGroup(groupName string) *CallbackManager {
	if groupName == "" {
		return nil
	}

	groupName = strings.ToLower(groupName)
	for _, manager := range GetServer().GetCallbackManagers() {
		if manager.GroupName == groupName {
			return manager
		}
	}

	return nil
}

func findPartitionManagerByTopic(manager *CallbackManager, topic string) []*PartitionManager {
	if topic == "" || manager == nil {
		return nil
	}

	found := false
	var res []*PartitionManager

	for _, t := range manager.Topics {
		if t == topic {
			found = true
			break
		}
	}

	if found {
		for _, partitionManager := range manager.GetPartitionManagers() {
			if partitionManager.Topic == topic {
				res = append(res, partitionManager)
			}
		}
	}

	return res
}

func init() {
	// new REST interface

	// /config, Get config object
	GetServer().GetAdminServerRouter().HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
		code := 0
		jsonify(w, r, GetServer().GetConfig(), code)
	})

	// /callbacks, Get CallbackManagers
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks", func(w http.ResponseWriter, r *http.Request) {
		code := 0

		var res []callbackManagerData

		for _, manager := range GetServer().GetCallbackManagers() {
			res = append(res, callbackManagerData{
				Url:       manager.Url,
				GroupName: manager.GroupName,
				Topics:    manager.Topics,
			})
		}

		jsonify(w, r, res, code)
	})

	// /callbacks/{group}, Get specified CallbackManager
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}", func(w http.ResponseWriter, r *http.Request) {
		if manager := findCallbackManagerByGroup(mux.Vars(r)["group"]); manager != nil {
			code := 0
			jsonify(w, r, callbackManagerData{
				Url:       manager.Url,
				GroupName: manager.GroupName,
				Topics:    manager.Topics,
			}, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/topics/{topic}, Get subscribed partitions of specified topics
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/topics/{topic}", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			var topics []string

			switch muxVars["topic"] {
			case "*", "":
				// get first topic
				topics = manager.Topics
			default:
				topics = append(topics, muxVars["topic"])
			}

			var result []topicPartitionsData
			code := 0

			for _, topic := range topics {
				if partitionManagers := findPartitionManagerByTopic(manager, topic); len(partitionManagers) > 0 {
					// found partitionManager matches this topic
					var res topicPartitionsData

					res.Url = manager.Url
					res.GroupName = manager.GroupName
					res.Topic = topic

					for _, partitionManager := range partitionManagers {
						res.Partitions = append(res.Partitions, partitionManager.Partition)
					}

					result = append(result, res)
				}
			}

			jsonify(w, r, result, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/topics/{topic}/partitions/{partition}, Get PartitionManager
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/topics/{topic}/partitions/{partition}", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			var topics []string

			switch muxVars["topic"] {
			case "*", "":
				// get first topic
				topics = manager.Topics
			default:
				topics = append(topics, muxVars["topic"])
			}

			var result []partitionManagerData
			code := 0

			for _, topic := range topics {
				if partitionManagers := findPartitionManagerByTopic(manager, topic); len(partitionManagers) > 0 {
					// found partitionManager matches this topic
					for _, partitionManager := range partitionManagers {
						var res partitionManagerData
						res.Url = manager.Url
						res.GroupName = manager.GroupName
						res.Topic = topic
						res.Partition = partitionManager.Partition
						res.Arbiter = partitionManager.GetArbiter().GetStat()
						res.PartitionConsumer = partitionManager.GetPartitionConsumer().GetStat()
						res.Transporter = partitionManager.GetTransporter().GetStat()

						result = append(result, res)
					}
				}
			}

			jsonify(w, r, result, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/offsets, Get OffsetManager
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/offsets", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			code := 0

			rawOffsets := manager.GetOffsetManager().GetOffsets()
			// convert OffsetMap keys to string
			offsets := make(map[string]map[string]int64)
			for topic, partitionOffsets := range rawOffsets {
				offsets[topic] = make(map[string]int64)
				for partition, offset := range partitionOffsets {
					offsets[topic][strconv.FormatInt(int64(partition), 10)] = offset
				}
			}

			jsonify(w, r, offsets, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/offsets/storages, Get OffsetStorage
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/offsets/storages", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			// TODO, add offset storage stats
			code := 0
			jsonify(w, r, nil, code)
			return
		}

		http.NotFound(w, r)
	})
}
<commit_msg>Apply partiton filter on stat request /callbacks/{group}/topics/{topic}/partitions/{partition}<commit_after>package main

import (
	"net/http"
	"strconv"
	"strings"

	"github.com/gorilla/mux"
)

type callbackManagerData struct {
	Url       string   `json:"url"`
	GroupName string   `json:"group"`
	Topics    []string `json:"topics"`
}

type topicPartitionsData struct {
	Url        string  `json:"url"`
	GroupName  string  `json:"group"`
	Topic      string  `json:"topic"`
	Partitions []int32 `json:"partitions"`
}

type partitionManagerData struct {
	Url               string      `json:"url"`
	GroupName         string      `json:"group"`
	Topic             string      `json:"topic"`
	Partition         int32       `json:"partition"`
	PartitionConsumer interface{} `json:"partition_consumer"`
	Arbiter           interface{} `json:"arbiter"`
	Transporter       interface{} `json:"transporter"`
}

func findCallbackManagerByGroup(groupName string) *CallbackManager {
	if groupName == "" {
		return nil
	}

	groupName = strings.ToLower(groupName)
	for _, manager := range GetServer().GetCallbackManagers() {
		if manager.GroupName == groupName {
			return manager
		}
	}

	return nil
}

func findPartitionManagerByTopic(manager *CallbackManager, topic string) []*PartitionManager {
	if topic == "" || manager == nil {
		return nil
	}

	found := false
	var res []*PartitionManager

	for _, t := range manager.Topics {
		if t == topic {
			found = true
			break
		}
	}

	if found {
		for _, partitionManager := range manager.GetPartitionManagers() {
			if partitionManager.Topic == topic {
				res = append(res, partitionManager)
			}
		}
	}

	return res
}

func init() {
	// new REST interface

	// /config, Get config object
	GetServer().GetAdminServerRouter().HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
		code := 0
		jsonify(w, r, GetServer().GetConfig(), code)
	})

	// /callbacks, Get CallbackManagers
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks", func(w http.ResponseWriter, r *http.Request) {
		code := 0

		var res []callbackManagerData

		for _, manager := range GetServer().GetCallbackManagers() {
			res = append(res, callbackManagerData{
				Url:       manager.Url,
				GroupName: manager.GroupName,
				Topics:    manager.Topics,
			})
		}

		jsonify(w, r, res, code)
	})

	// /callbacks/{group}, Get specified CallbackManager
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}", func(w http.ResponseWriter, r *http.Request) {
		if manager := findCallbackManagerByGroup(mux.Vars(r)["group"]); manager != nil {
			code := 0
			jsonify(w, r, callbackManagerData{
				Url:       manager.Url,
				GroupName: manager.GroupName,
				Topics:    manager.Topics,
			}, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/topics/{topic}, Get subscribed partitions of specified topics
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/topics/{topic}", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			var topics []string

			switch muxVars["topic"] {
			case "*", "":
				// get first topic
				topics = manager.Topics
			default:
				topics = append(topics, muxVars["topic"])
			}

			var result []topicPartitionsData
			code := 0

			for _, topic := range topics {
				if partitionManagers := findPartitionManagerByTopic(manager, topic); len(partitionManagers) > 0 {
					// found partitionManager matches this topic
					var res topicPartitionsData

					res.Url = manager.Url
					res.GroupName = manager.GroupName
					res.Topic = topic

					for _, partitionManager := range partitionManagers {
						res.Partitions = append(res.Partitions, partitionManager.Partition)
					}

					result = append(result, res)
				}
			}

			jsonify(w, r, result, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/topics/{topic}/partitions/{partition}, Get PartitionManager
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/topics/{topic}/partitions/{partition}", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			var topics []string

			switch muxVars["topic"] {
			case "*", "":
				// get all topics
				topics = manager.Topics
			default:
				topics = append(topics, muxVars["topic"])
			}

			var result []partitionManagerData
			code := 0

			for _, topic := range topics {
				if partitionManagers := findPartitionManagerByTopic(manager, topic); len(partitionManagers) > 0 {
					// found partitionManager matches this topic

					// find partitions matches our need
					applyFilter := false
					switch muxVars["partition"] {
					case "*", "":
						// get all partitions
						applyFilter = false
					default:
						applyFilter = true
					}

					var partitionFilter int32

					if applyFilter {
						if partition, err := strconv.ParseInt(muxVars["partition"], 10, 32 /* partition in int32 */); err != nil {
							applyFilter = false
						} else {
							partitionFilter = int32(partition)
						}
					}
					for _, partitionManager := range partitionManagers {
						if !applyFilter || partitionManager.Partition == partitionFilter {
							var res partitionManagerData
							res.Url = manager.Url
							res.GroupName = manager.GroupName
							res.Topic = topic
							res.Partition = partitionManager.Partition
							res.Arbiter = partitionManager.GetArbiter().GetStat()
							res.PartitionConsumer = partitionManager.GetPartitionConsumer().GetStat()
							res.Transporter = partitionManager.GetTransporter().GetStat()

							result = append(result, res)
						}
					}
				}
			}

			jsonify(w, r, result, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/offsets, Get OffsetManager
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/offsets", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			code := 0

			rawOffsets := manager.GetOffsetManager().GetOffsets()
			// convert OffsetMap keys to string
			offsets := make(map[string]map[string]int64)
			for topic, partitionOffsets := range rawOffsets {
				offsets[topic] = make(map[string]int64)
				for partition, offset := range partitionOffsets {
					offsets[topic][strconv.FormatInt(int64(partition), 10)] = offset
				}
			}

			jsonify(w, r, offsets, code)
			return
		}

		http.NotFound(w, r)
	})

	// /callbacks/{group}/offsets/storages, Get OffsetStorage
	GetServer().GetAdminServerRouter().HandleFunc("/callbacks/{group}/offsets/storages", func(w http.ResponseWriter, r *http.Request) {
		muxVars := mux.Vars(r)

		if manager := findCallbackManagerByGroup(muxVars["group"]); manager != nil {
			// TODO, add offset storage stats
			code := 0
			jsonify(w, r, nil, code)
			return
		}

		http.NotFound(w, r)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"reflect"
	"strings"

	cli "gopkg.in/urfave/cli.v2"
	yaml "gopkg.in/yaml.v2"

	"github.com/jgillich/nixbench/modules"
)

// VERSION is set at build time
var VERSION = "master"

func main() {

	app := &cli.App{
		Name:        "nixbench",
		Usage:       "A better benchmarking tool for servers",
		Description: fmt.Sprintf("Loaded modules: %s", strings.Trim(fmt.Sprintf("%v", reflect.ValueOf(modules.Modules).MapKeys()), "[]")),
		Version:     VERSION,
		Flags: []cli.Flag{
			&cli.BoolFlag{
				Name:  "yaml",
				Usage: "Output as yaml",
			},
			&cli.StringSliceFlag{
				Name:    "modules",
				Aliases: []string{"m"},
				Usage:   "Modules to enable",
				Value:   cli.NewStringSlice("host", "cpu", "disk", "net"),
			},
		},
		Action: func(c *cli.Context) error {
			if !c.Bool("yaml") {
				fmt.Printf("nixbench %s - https://github.com/jgillich/nixbench", VERSION)
			}

			for _, name := range c.StringSlice("modules") {
				module, ok := modules.Modules[name]

				if !ok {
					return fmt.Errorf("unknown module '%s'", name)
				}

				if err := module.Run(); err != nil {
					return err
				}

				if c.Bool("yaml") {
					var r map[string]interface{} = map[string]interface{}{}
					r[name] = module
					yml, err := yaml.Marshal(r)
					if err != nil {
						return err
					}
					fmt.Printf(string(yml))
				} else {
					fmt.Printf("\n\n%s\n", name)
					for i := 1; i <= len(name); i++ {
						fmt.Print("-")
					}
					fmt.Print("\n")
					module.Print()
				}
			}

			return nil
		},
	}

	app.Run(os.Args)
}
<commit_msg>add --all flag<commit_after>package main

import (
	"fmt"
	"os"
	"strings"

	cli "gopkg.in/urfave/cli.v2"
	yaml "gopkg.in/yaml.v2"

	"github.com/jgillich/nixbench/modules"
)

// VERSION is set at build time
var VERSION = "master"

func main() {

	moduleNames := []string{}
	for key := range modules.Modules {
		moduleNames = append(moduleNames, key)
	}

	app := &cli.App{
		Name:        "nixbench",
		Usage:       "A better benchmarking tool for servers",
		Description: fmt.Sprintf("Loaded modules: %s", strings.Trim(fmt.Sprintf("%v", moduleNames), "[]")),
		Version:     VERSION,
		Flags: []cli.Flag{
			&cli.BoolFlag{
				Name:  "yaml",
				Usage: "Output as yaml",
			},
			&cli.BoolFlag{
				Name:  "all",
				Usage: "Run all modules",
			},
			&cli.StringSliceFlag{
				Name:    "modules",
				Aliases: []string{"m"},
				Usage:   "Modules to enable",
				Value:   cli.NewStringSlice("host", "cpu", "disk", "net"),
			},
		},
		Action: func(c *cli.Context) error {
			if !c.Bool("yaml") {
				fmt.Printf("nixbench %s - https://github.com/jgillich/nixbench", VERSION)
			}

			enabledModules := c.StringSlice("modules")

			if c.Bool("all") {
				enabledModules = moduleNames
			}

			for _, name := range enabledModules {
				module, ok := modules.Modules[name]

				if !ok {
					return fmt.Errorf("unknown module '%s'", name)
				}

				if err := module.Run(); err != nil {
					return err
				}

				if c.Bool("yaml") {
					var r map[string]interface{} = map[string]interface{}{}
					r[name] = module
					yml, err := yaml.Marshal(r)
					if err != nil {
						return err
					}
					fmt.Printf(string(yml))
				} else {
					fmt.Printf("\n\n%s\n", name)
					for i := 1; i <= len(name); i++ {
						fmt.Print("-")
					}
					fmt.Print("\n")
					module.Print()
				}
			}

			return nil
		},
	}

	app.Run(os.Args)
}
<|endoftext|>