<commit_before>//
//  telgo
//
//
//  Copyright (C) 2015 Christian Pointner <equinox@helsinki.at>
//
//  This file is part of telgo.
//
//  telgo is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  any later version.
//
//  telgo is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with telgo. If not, see <http://www.gnu.org/licenses/>.
//

// Package telgo contains a simple telnet server which can be used as a
// control/debug interface for applications.
// The telgo telnet server does all the client handling and runs configurable
// commands as go routines. It also supports handling of basic inline telnet
// commands used by variaus telnet clients to configure the client connection.
// For now every negotiable telnet option will be discarded but the telnet
// command IP (interrupt process) is understood and can be used to terminate
// long running user commands.
package telgo

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
)

var (
	tl = log.New(os.Stderr, "[telnet]\t", log.LstdFlags)
)

const (
	EOT  = byte(4)
	IP   = byte(244)
	WILL = byte(251)
	WONT = byte(252)
	DO   = byte(253)
	DONT = byte(254)
	IAC  = byte(255)
)

// This is the signature of telgo command functions. It receives a pointer to
// the telgo client struct and a slice of strings containing the arguments the
// user has supplied. The first argument is always the command name itself.
// If this function returns true the client connection will be terminated.
type TelgoCmd func(c *TelnetClient, args []string) bool
type TelgoCmdList map[string]TelgoCmd

// This struct is used to export the raw tcp connection to the client as well as
// the UserData which got supplied to NewTelnetServer.
// The Cancel channel will get ready for reading when the user hits Ctrl-C or
// the connection got terminated. This can be used for long running telgo commands
// to be aborted.
type TelnetClient struct {
	Conn     net.Conn
	UserData interface{}
	Cancel   chan bool
	scanner  *bufio.Scanner
	writer   *bufio.Writer
	prompt   string
	commands *TelgoCmdList
	iacout   chan []byte
	stdout   chan []byte
}

func newTelnetClient(conn net.Conn, prompt string, commands *TelgoCmdList, userdata interface{}) (c *TelnetClient) {
	tl.Println("telgo: new client from:", conn.RemoteAddr())
	c = &TelnetClient{}
	c.Conn = conn
	c.scanner = bufio.NewScanner(conn)
	c.writer = bufio.NewWriter(conn)
	c.prompt = prompt
	c.commands = commands
	c.UserData = userdata
	c.stdout = make(chan []byte)
	c.Cancel = make(chan bool, 1)
	// the telnet split function needs some closures to handle OOB telnet commands
	c.iacout = make(chan []byte)
	lastiiac := 0
	c.scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		return scanLines(data, atEOF, c.iacout, &lastiiac)
	})
	return c
}

// This writes a 'raw' string to the client. For the most part the usage of Say
// and Sayln is recommended. WriteString will take care of escaping IAC bytes
// inside your string.
func (c *TelnetClient) WriteString(text string) {
	c.stdout <- bytes.Replace([]byte(text), []byte{IAC}, []byte{IAC, IAC}, -1)
}

// This is a simple Printf like interface which sends responses to the client.
func (c *TelnetClient) Say(format string, a ...interface{}) {
	c.WriteString(fmt.Sprintf(format, a...))
}

// This is the same as Say but also adds a new-line at the end of the string.
func (c *TelnetClient) Sayln(format string, a ...interface{}) {
	c.WriteString(fmt.Sprintf(format, a...) + "\r\n")
}

// TODO: fix split function to respect "" and ''
func (c *TelnetClient) handleCmd(cmdstr string, done chan<- bool) {
	quit := false
	defer func() { done <- quit }()

	cmdslice := strings.Fields(cmdstr)
	if len(cmdslice) == 0 || cmdslice[0] == "" {
		return
	}

	select {
	case <-c.Cancel: // consume potentially pending cancel request
	default:
	}
	for cmd, cmdfunc := range *c.commands {
		if cmdslice[0] == cmd {
			quit = cmdfunc(c, cmdslice)
			return
		}
	}
	c.Sayln("unknown command '%s'", cmdslice[0])
}

func handleIac(iac []byte, iacout chan<- []byte) {
	switch iac[1] {
	case WILL, WONT: // Don't accept any proposed options
		iac[1] = DONT
	case DO, DONT:
		iac[1] = WONT
	case IP:
		// pass this through to client.handle which will cancel the process
	default:
		tl.Printf("ignoring unimplemented telnet command: %X", iac[1])
		return
	}
	iacout <- iac
}

func dropCR(data []byte) []byte {
	if len(data) > 0 && data[len(data)-1] == '\r' {
		return data[0 : len(data)-1]
	}
	return data
}

func dropIAC(data []byte) []byte {
	var token []byte
	iiac := 0
	for {
		niiac := bytes.IndexByte(data[iiac:], IAC)
		if niiac >= 0 {
			token = append(token, data[iiac:iiac+niiac]...)
			iiac += niiac
			if (len(data) - iiac) < 2 {
				return token
			}
			switch data[iiac+1] {
			case DONT, DO, WONT, WILL:
				if (len(data) - iiac) < 3 {
					return token
				}
				iiac += 3
			case IAC:
				token = append(token, IAC)
				fallthrough
			default:
				iiac += 2
			}
		} else {
			token = append(token, data[iiac:]...)
			break
		}
	}
	return token
}

func compareIdx(a, b int) int {
	if a < 0 {
		a = int(^uint(0) >> 1)
	}
	if b < 0 {
		b = int(^uint(0) >> 1)
	}
	return a - b
}

func scanLines(data []byte, atEOF bool, iacout chan<- []byte, lastiiac *int) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	inl := bytes.IndexByte(data, '\n') // index of first newline character
	ieot := bytes.IndexByte(data, EOT) // index of first End of Transmission

	iiac := *lastiiac
	for {
		niiac := bytes.IndexByte(data[iiac:], IAC) // index of first/next telnet IAC
		if niiac >= 0 {
			iiac += niiac
		} else {
			iiac = niiac
		}

		if inl >= 0 && compareIdx(inl, ieot) < 0 && compareIdx(inl, iiac) < 0 {
			*lastiiac = 0
			return inl + 1, dropCR(dropIAC(data[0:inl])), nil // found a complete line
		}
		if ieot >= 0 && compareIdx(ieot, iiac) < 0 {
			*lastiiac = 0
			return ieot + 1, data[ieot : ieot+1], nil // found a EOT (aka Ctrl-D)
		}
		if iiac >= 0 {
			l := 2
			if (len(data) - iiac) < 2 {
				return 0, nil, nil // data does not yet contain the telnet command code -> need more data
			}
			switch data[iiac+1] {
			case DONT, DO, WONT, WILL:
				if (len(data) - iiac) < 3 {
					return 0, nil, nil // this is a 3-byte command and data does not yet contain the option code -> need more data
				}
				l = 3
			case IAC:
				iiac += 2
				continue
			}
			handleIac(data[iiac:iiac+l], iacout)
			iiac += l
			*lastiiac = iiac
		} else {
			break
		}
	}
	if atEOF {
		return len(data), dropCR(data), nil // allow last line to have no new line
	}
	return 0, nil, nil // we have found none of the escape codes -> need more data
}

func (c *TelnetClient) recv(in chan<- string) {
	defer close(in)

	for c.scanner.Scan() {
		b := c.scanner.Bytes()
		if len(b) > 0 && b[0] == EOT {
			tl.Printf("telgo(%s): Ctrl-D received, closing", c.Conn.RemoteAddr())
			return
		}
		in <- string(b)
	}
	if err := c.scanner.Err(); err != nil {
		tl.Printf("telgo(%s): recv() error: %s", c.Conn.RemoteAddr(), err)
	} else {
		tl.Printf("telgo(%s): Connection closed by foreign host", c.Conn.RemoteAddr())
	}
}

func (c *TelnetClient) cancel() {
	select {
	case c.Cancel <- true:
	default: // process got canceled already
	}
}

func (c *TelnetClient) send(quit <-chan bool) {
	for {
		select {
		case <-quit:
			return
		case iac := <-c.iacout:
			if iac[1] == IP {
				c.cancel()
			} else {
				c.writer.Write(iac)
				c.writer.Flush()
			}
		case data := <-c.stdout:
			c.writer.Write(data)
			c.writer.Flush()
		}
	}
}

func (c *TelnetClient) handle() {
	defer c.Conn.Close()

	in := make(chan string)
	go c.recv(in)

	quit_send := make(chan bool)
	go c.send(quit_send)
	defer func() { quit_send <- true }()

	defer c.cancel() // make sure to cancel possible running job when closing connection

	done := make(chan bool)
	busy := false
	c.WriteString(c.prompt)
	for {
		select {
		case cmd, ok := <-in:
			if !ok { // Ctrl-D or recv error (connection closed...)
				return
			}
			if !busy { // ignore everything except Ctrl-D while executing a command
				if len(cmd) > 0 {
					go c.handleCmd(cmd, done)
					busy = true
				} else {
					c.WriteString(c.prompt)
				}
			}
		case exit := <-done:
			if exit {
				return
			}
			c.WriteString(c.prompt)
			busy = false
		}
	}
}

type TelnetServer struct {
	addr     string
	prompt   string
	commands TelgoCmdList
	userdata interface{}
}

// This creates a new telnet server. addr is the address to bind/listen to on and will be passed through
// to net.Listen(). The prompt will be sent to the client whenever the telgo server is ready for a new command.
// TelgoCmdList is a list of available commands and userdata will be made available to called telgo
// commands through the client struct.
func NewTelnetServer(addr, prompt string, commands TelgoCmdList, userdata interface{}) (s *TelnetServer) {
	s = &TelnetServer{}
	s.addr = addr
	s.prompt = prompt
	s.commands = commands
	s.userdata = userdata
	return s
}

// This runs the telnet server and spawns go routines for every connecting client.
func (self *TelnetServer) Run() error {
	tl.Println("telgo: listening on", self.addr)

	server, err := net.Listen("tcp", self.addr)
	if err != nil {
		tl.Println("telgo: Listen() Error:", err)
		return err
	}

	for {
		conn, err := server.Accept()
		if err != nil {
			tl.Println("telgo: Accept() Error:", err)
			return err
		}

		c := newTelnetClient(conn, self.prompt, &self.commands, self.userdata)
		go c.handle()
	}
}
<commit_msg>nicer IAC handling<commit_after>//
//  telgo
//
//
//  Copyright (C) 2015 Christian Pointner <equinox@helsinki.at>
//
//  This file is part of telgo.
//
//  telgo is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  any later version.
//
//  telgo is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with telgo. If not, see <http://www.gnu.org/licenses/>.
//

// Package telgo contains a simple telnet server which can be used as a
// control/debug interface for applications.
// The telgo telnet server does all the client handling and runs configurable
// commands as go routines. It also supports handling of basic inline telnet
// commands used by variaus telnet clients to configure the client connection.
// For now every negotiable telnet option will be discarded but the telnet
// command IP (interrupt process) is understood and can be used to terminate
// long running user commands.
package telgo

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
)

var (
	tl = log.New(os.Stderr, "[telnet]\t", log.LstdFlags)
)

const (
	EOT  = byte(4)
	IAC  = byte(255)
	DONT = byte(254)
	DO   = byte(253)
	WONT = byte(252)
	WILL = byte(251)
	SB   = byte(250)
	GA   = byte(249)
	EL   = byte(248)
	EC   = byte(247)
	AYT  = byte(246)
	AO   = byte(245)
	IP   = byte(244)
	BREA = byte(243)
	DM   = byte(242)
	NOP  = byte(241)
	SE   = byte(240)
)

type telnet_command struct {
	length      int
	name        string
	description string
}

var (
	telnet_commands = map[byte]telnet_command{
		DONT: telnet_command{3, "DONT", "don't use option"},
		DO:   telnet_command{3, "DO", "do use option"},
		WONT: telnet_command{3, "WONT", "won't use option"},
		WILL: telnet_command{3, "WILL", "will use option"},
		SB:   telnet_command{2, "SB", "Begin of subnegotiation parameters"},
		GA:   telnet_command{2, "GA", "go ahead signal"},
		EL:   telnet_command{2, "EL", "erase line"},
		EC:   telnet_command{2, "EC", "erase character"},
		AYT:  telnet_command{2, "AYT", "are you there"},
		AO:   telnet_command{2, "AO", "abort output"},
		IP:   telnet_command{2, "IP", "interrupt process"},
		BREA: telnet_command{2, "BREA", "break"},
		DM:   telnet_command{2, "DM", "data mark"},
		NOP:  telnet_command{2, "NOP", "no operation"},
		SE:   telnet_command{2, "SE", "End of subnegotiation parameters"},
	}
)

// This is the signature of telgo command functions. It receives a pointer to
// the telgo client struct and a slice of strings containing the arguments the
// user has supplied. The first argument is always the command name itself.
// If this function returns true the client connection will be terminated.
type TelgoCmd func(c *TelnetClient, args []string) bool
type TelgoCmdList map[string]TelgoCmd

// This struct is used to export the raw tcp connection to the client as well as
// the UserData which got supplied to NewTelnetServer.
// The Cancel channel will get ready for reading when the user hits Ctrl-C or
// the connection got terminated. This can be used for long running telgo commands
// to be aborted.
type TelnetClient struct {
	Conn     net.Conn
	UserData interface{}
	Cancel   chan bool
	scanner  *bufio.Scanner
	writer   *bufio.Writer
	prompt   string
	commands *TelgoCmdList
	iacout   chan []byte
	stdout   chan []byte
}

func newTelnetClient(conn net.Conn, prompt string, commands *TelgoCmdList, userdata interface{}) (c *TelnetClient) {
	tl.Println("telgo: new client from:", conn.RemoteAddr())
	c = &TelnetClient{}
	c.Conn = conn
	c.scanner = bufio.NewScanner(conn)
	c.writer = bufio.NewWriter(conn)
	c.prompt = prompt
	c.commands = commands
	c.UserData = userdata
	c.stdout = make(chan []byte)
	c.Cancel = make(chan bool, 1)
	// the telnet split function needs some closures to handle OOB telnet commands
	c.iacout = make(chan []byte)
	lastiiac := 0
	c.scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		return scanLines(data, atEOF, c.iacout, &lastiiac)
	})
	return c
}

// This writes a 'raw' string to the client. For the most part the usage of Say
// and Sayln is recommended. WriteString will take care of escaping IAC bytes
// inside your string.
func (c *TelnetClient) WriteString(text string) {
	c.stdout <- bytes.Replace([]byte(text), []byte{IAC}, []byte{IAC, IAC}, -1)
}

// This is a simple Printf like interface which sends responses to the client.
func (c *TelnetClient) Say(format string, a ...interface{}) {
	c.WriteString(fmt.Sprintf(format, a...))
}

// This is the same as Say but also adds a new-line at the end of the string.
func (c *TelnetClient) Sayln(format string, a ...interface{}) {
	c.WriteString(fmt.Sprintf(format, a...) + "\r\n")
}

// TODO: fix split function to respect "" and ''
func (c *TelnetClient) handleCmd(cmdstr string, done chan<- bool) {
	quit := false
	defer func() { done <- quit }()

	cmdslice := strings.Fields(cmdstr)
	if len(cmdslice) == 0 || cmdslice[0] == "" {
		return
	}

	select {
	case <-c.Cancel: // consume potentially pending cancel request
	default:
	}
	for cmd, cmdfunc := range *c.commands {
		if cmdslice[0] == cmd {
			quit = cmdfunc(c, cmdslice)
			return
		}
	}
	c.Sayln("unknown command '%s'", cmdslice[0])
}

func handleIac(iac []byte, iacout chan<- []byte) {
	switch iac[1] {
	case WILL, WONT: // Don't accept any proposed options
		iac[1] = DONT
	case DO, DONT:
		iac[1] = WONT
	case IP:
		// pass this through to client.handle which will cancel the process
	default:
		tl.Printf("ignoring unimplemented telnet command: %s (%s)", telnet_commands[iac[1]].name, telnet_commands[iac[1]].description)
		return
	}
	iacout <- iac
}

func dropCR(data []byte) []byte {
	if len(data) > 0 && data[len(data)-1] == '\r' {
		return data[0 : len(data)-1]
	}
	return data
}

func dropIAC(data []byte) []byte {
	var token []byte
	iiac := 0
	for {
		niiac := bytes.IndexByte(data[iiac:], IAC)
		if niiac >= 0 {
			token = append(token, data[iiac:iiac+niiac]...)
			iiac += niiac
			if (len(data) - iiac) < 2 { // check if the data at least contains a command code
				return token // something is fishy.. found an IAC but this is the last byte of the token...
			}
			l := telnet_commands[data[iiac+1]].length
			if (len(data) - iiac) < l { // check if the command is complete
				return token // something is fishy.. found an IAC but the command is too short...
			}
			if data[iiac+1] == IAC { // escaped IAC found
				token = append(token, IAC)
			}
			iiac += l
		} else {
			token = append(token, data[iiac:]...)
			break
		}
	}
	return token
}

func compareIdx(a, b int) int {
	if a < 0 {
		a = int(^uint(0) >> 1)
	}
	if b < 0 {
		b = int(^uint(0) >> 1)
	}
	return a - b
}

func scanLines(data []byte, atEOF bool, iacout chan<- []byte, lastiiac *int) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	inl := bytes.IndexByte(data, '\n') // index of first newline character
	ieot := bytes.IndexByte(data, EOT) // index of first End of Transmission

	iiac := *lastiiac
	for {
		niiac := bytes.IndexByte(data[iiac:], IAC) // index of first/next telnet IAC
		if niiac >= 0 {
			iiac += niiac
		} else {
			iiac = niiac
		}

		if inl >= 0 && compareIdx(inl, ieot) < 0 && compareIdx(inl, iiac) < 0 {
			*lastiiac = 0
			return inl + 1, dropCR(dropIAC(data[0:inl])), nil // found a complete line
		}
		if ieot >= 0 && compareIdx(ieot, iiac) < 0 {
			*lastiiac = 0
			return ieot + 1, data[ieot : ieot+1], nil // found a EOT (aka Ctrl-D was hit)
		}
		if iiac >= 0 {
			if (len(data) - iiac) < 2 {
				return 0, nil, nil // data does not yet contain the telnet command code -> need more data
			}
			l := telnet_commands[data[iiac+1]].length
			if (len(data) - iiac) < l {
				return 0, nil, nil // data does not yet contain the complete telnet command -> need more data
			}
			handleIac(data[iiac:iiac+l], iacout)
			iiac += l
			*lastiiac = iiac
		} else {
			break
		}
	}
	if atEOF {
		return len(data), dropCR(data), nil // allow last line to have no new line
	}
	return 0, nil, nil // we have found none of the escape codes -> need more data
}

func (c *TelnetClient) recv(in chan<- string) {
	defer close(in)

	for c.scanner.Scan() {
		b := c.scanner.Bytes()
		if len(b) > 0 && b[0] == EOT {
			tl.Printf("telgo(%s): Ctrl-D received, closing", c.Conn.RemoteAddr())
			return
		}
		in <- string(b)
	}
	if err := c.scanner.Err(); err != nil {
		tl.Printf("telgo(%s): recv() error: %s", c.Conn.RemoteAddr(), err)
	} else {
		tl.Printf("telgo(%s): Connection closed by foreign host", c.Conn.RemoteAddr())
	}
}

func (c *TelnetClient) cancel() {
	select {
	case c.Cancel <- true:
	default: // process got canceled already
	}
}

func (c *TelnetClient) send(quit <-chan bool) {
	for {
		select {
		case <-quit:
			return
		case iac := <-c.iacout:
			if iac[1] == IP {
				c.cancel()
			} else {
				c.writer.Write(iac)
				c.writer.Flush()
			}
		case data := <-c.stdout:
			c.writer.Write(data)
			c.writer.Flush()
		}
	}
}

func (c *TelnetClient) handle() {
	defer c.Conn.Close()

	in := make(chan string)
	go c.recv(in)

	quit_send := make(chan bool)
	go c.send(quit_send)
	defer func() { quit_send <- true }()

	defer c.cancel() // make sure to cancel possible running job when closing connection

	done := make(chan bool)
	busy := false
	c.WriteString(c.prompt)
	for {
		select {
		case cmd, ok := <-in:
			if !ok { // Ctrl-D or recv error (connection closed...)
				return
			}
			if !busy { // ignore everything except Ctrl-D while executing a command
				if len(cmd) > 0 {
					go c.handleCmd(cmd, done)
					busy = true
				} else {
					c.WriteString(c.prompt)
				}
			}
		case exit := <-done:
			if exit {
				return
			}
			c.WriteString(c.prompt)
			busy = false
		}
	}
}

type TelnetServer struct {
	addr     string
	prompt   string
	commands TelgoCmdList
	userdata interface{}
}

// This creates a new telnet server. addr is the address to bind/listen to on and will be passed through
// to net.Listen(). The prompt will be sent to the client whenever the telgo server is ready for a new command.
// TelgoCmdList is a list of available commands and userdata will be made available to called telgo
// commands through the client struct.
func NewTelnetServer(addr, prompt string, commands TelgoCmdList, userdata interface{}) (s *TelnetServer) {
	s = &TelnetServer{}
	s.addr = addr
	s.prompt = prompt
	s.commands = commands
	s.userdata = userdata
	return s
}

// This runs the telnet server and spawns go routines for every connecting client.
func (self *TelnetServer) Run() error {
	tl.Println("telgo: listening on", self.addr)

	server, err := net.Listen("tcp", self.addr)
	if err != nil {
		tl.Println("telgo: Listen() Error:", err)
		return err
	}

	for {
		conn, err := server.Accept()
		if err != nil {
			tl.Println("telgo: Accept() Error:", err)
			return err
		}

		c := newTelnetClient(conn, self.prompt, &self.commands, self.userdata)
		go c.handle()
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The ContainerOps Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package router

import (
	"gopkg.in/macaron.v1"

	"github.com/containerops/dockyard/handler"
)

func SetRouters(m *macaron.Macaron) {
	m.Get("/", handler.IndexV1Handler)

	//Docker Registry V1

	//Docker Registry V2

	//Appc Discovery
	m.Group("/appc", func() {
		//Discovery
		m.Get("/:namespace/:repository/?ac-discovery=1", handler.AppcDiscoveryV1Handler)
	})

	//Software Discovery

	//VM Image Discovery

	//Management APIs
}
<commit_msg>add v1 version in appc router definition<commit_after>/*
Copyright 2015 The ContainerOps Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package router

import (
	"gopkg.in/macaron.v1"

	"github.com/containerops/dockyard/handler"
)

func SetRouters(m *macaron.Macaron) {
	m.Get("/", handler.IndexV1Handler)

	//Docker Registry V1

	//Docker Registry V2

	//Appc Discovery
	m.Group("/appc", func() {
		m.Group("/v1", func() {
			//Discovery
			m.Get("/:namespace/:repository/?ac-discovery=1", handler.AppcDiscoveryV1Handler)
		})
	})

	//Software Discovery

	//VM Image Discovery

	//Management APIs
}
<|endoftext|>


<commit_before>package router

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

	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/router"
	"github.com/micro/go-micro/router/handler"
	pb "github.com/micro/go-micro/router/proto"
	"github.com/micro/go-micro/util/log"
)

var (
	// Name of the router microservice
	Name = "go.micro.router"
	// Address is the router microservice bind address
	Address = ":8084"
	// Router is the router gossip bind address
	Router = ":9093"
	// Network is the network id
	Network = "local"
	// Topic is router adverts topic
	Topic = "go.micro.router.adverts"
)

// Sub processes router events
type sub struct {
	router router.Router
}

// Process processes router adverts
func (s *sub) Process(ctx context.Context, advert *pb.Advert) error {
	log.Logf("[router] received advert from: %s", advert.Id)
	if advert.Id == s.router.Options().Id {
		log.Logf("[router] skipping advert")
		return nil
	}

	var events []*router.Event
	for _, event := range advert.Events {
		route := router.Route{
			Service: event.Route.Service,
			Address: event.Route.Address,
			Gateway: event.Route.Gateway,
			Network: event.Route.Network,
			Link:    event.Route.Link,
			Metric:  int(event.Route.Metric),
		}

		e := &router.Event{
			Type:      router.EventType(event.Type),
			Timestamp: time.Unix(0, advert.Timestamp),
			Route:     route,
		}

		events = append(events, e)
	}

	a := &router.Advert{
		Id:        advert.Id,
		Type:      router.AdvertType(advert.Type),
		Timestamp: time.Unix(0, advert.Timestamp),
		TTL:       time.Duration(advert.Ttl),
		Events:    events,
	}

	if err := s.router.Process(a); err != nil {
		return fmt.Errorf("[router] failed processing advert: %s", err)
	}

	return nil
}

// rtr is micro router
type rtr struct {
	// router is the micro router
	router.Router
	// publisher to publish router adverts
	micro.Publisher
}

// newRouter creates new micro router and returns it
func newRouter(service micro.Service, router router.Router) *rtr {
	s := &sub{
		router: router,
	}

	// register subscriber
	if err := micro.RegisterSubscriber(Topic, service.Server(), s); err != nil {
		log.Logf("[router] failed to subscribe to adverts: %s", err)
		os.Exit(1)
	}

	return &rtr{
		Router:    router,
		Publisher: micro.NewPublisher(Topic, service.Client()),
	}
}

// PublishAdverts publishes adverts for other routers to consume
func (r *rtr) PublishAdverts(ch <-chan *router.Advert) error {
	for advert := range ch {
		var events []*pb.Event
		for _, event := range advert.Events {
			route := &pb.Route{
				Service: event.Route.Service,
				Address: event.Route.Address,
				Gateway: event.Route.Gateway,
				Network: event.Route.Network,
				Link:    event.Route.Link,
				Metric:  int64(event.Route.Metric),
			}
			e := &pb.Event{
				Type:      pb.EventType(event.Type),
				Timestamp: event.Timestamp.UnixNano(),
				Route:     route,
			}
			events = append(events, e)
		}

		a := &pb.Advert{
			Id:        r.Options().Id,
			Type:      pb.AdvertType(advert.Type),
			Timestamp: advert.Timestamp.UnixNano(),
			Events:    events,
		}

		if err := r.Publish(context.Background(), a); err != nil {
			log.Logf("[router] error publishing advert: %v", err)
			return fmt.Errorf("error publishing advert: %v", err)
		}
	}

	return nil
}

// stop stops the micro router
func (r *rtr) Stop() error {
	// stop the router
	if err := r.Stop(); err != nil {
		return fmt.Errorf("failed to stop router: %v", err)
	}

	return nil
}

// run runs the micro server
func run(ctx *cli.Context, srvOpts ...micro.Option) {
	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	if len(ctx.GlobalString("server_name")) > 0 {
		Name = ctx.GlobalString("server_name")
	}
	if len(ctx.String("address")) > 0 {
		Address = ctx.String("address")
	}
	if len(ctx.String("router_address")) > 0 {
		Router = ctx.String("router")
	}
	if len(ctx.String("network_address")) > 0 {
		Network = ctx.String("network")
	}
	// default gateway address
	var gateway string
	if len(ctx.String("gateway_address")) > 0 {
		gateway = ctx.String("gateway")
	}

	// Initialise service
	service := micro.NewService(
		micro.Name(Name),
		micro.Address(Address),
		micro.RegisterTTL(time.Duration(ctx.GlobalInt("register_ttl"))*time.Second),
		micro.RegisterInterval(time.Duration(ctx.GlobalInt("register_interval"))*time.Second),
	)

	r := router.NewRouter(
		router.Id(service.Server().Options().Id),
		router.Address(Router),
		router.Network(Network),
		router.Registry(service.Client().Options().Registry),
		router.Gateway(gateway),
	)

	// register router handler
	pb.RegisterRouterHandler(
		service.Server(),
		&handler.Router{
			Router: r,
		},
	)

	// register the table handler
	pb.RegisterTableHandler(
		service.Server(),
		&handler.Table{
			Router: r,
		},
	)

	// create new micro router and start advertising routes
	rtr := newRouter(service, r)

	log.Log("[router] starting to advertise")

	advertChan, err := rtr.Advertise()
	if err != nil {
		log.Logf("[router] failed to start: %s", err)
		os.Exit(1)
	}

	var wg sync.WaitGroup

	errChan := make(chan error, 2)

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- rtr.PublishAdverts(advertChan)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- service.Run()
	}()

	// we block here until either service or server fails
	if err := <-errChan; err != nil {
		log.Logf("[router] error running the router: %v", err)
	}

	log.Log("[router] attempting to stop the router")

	// stop the router
	if err := r.Stop(); err != nil {
		log.Logf("[router] failed to stop: %s", err)
		os.Exit(1)
	}

	wg.Wait()

	log.Logf("[router] successfully stopped")
}

func Commands(options ...micro.Option) []cli.Command {
	command := cli.Command{
		Name:  "router",
		Usage: "Run the micro network router",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:   "router_address",
				Usage:  "Set the micro router address :9093",
				EnvVar: "MICRO_ROUTER_ADDRESS",
			},
			cli.StringFlag{
				Name:   "network_address",
				Usage:  "Set the micro network address: local",
				EnvVar: "MICRO_NETWORK_ADDRESS",
			},
			cli.StringFlag{
				Name:   "gateway_address",
				Usage:  "Set the micro default gateway address :9094",
				EnvVar: "MICRO_GATEWAY_ADDRESS",
			},
		},
		Action: func(ctx *cli.Context) {
			run(ctx, options...)
		},
	}

	for _, p := range Plugins() {
		if cmds := p.Commands(); len(cmds) > 0 {
			command.Subcommands = append(command.Subcommands, cmds...)
		}

		if flags := p.Flags(); len(flags) > 0 {
			command.Flags = append(command.Flags, flags...)
		}
	}

	return []cli.Command{command}
}
<commit_msg>Call start before Advertise<commit_after>package router

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

	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/router"
	"github.com/micro/go-micro/router/handler"
	pb "github.com/micro/go-micro/router/proto"
	"github.com/micro/go-micro/util/log"
)

var (
	// Name of the router microservice
	Name = "go.micro.router"
	// Address is the router microservice bind address
	Address = ":8084"
	// Router is the router gossip bind address
	Router = ":9093"
	// Network is the network id
	Network = "local"
	// Topic is router adverts topic
	Topic = "go.micro.router.adverts"
)

// Sub processes router events
type sub struct {
	router router.Router
}

// Process processes router adverts
func (s *sub) Process(ctx context.Context, advert *pb.Advert) error {
	log.Logf("[router] received advert from: %s", advert.Id)
	if advert.Id == s.router.Options().Id {
		log.Logf("[router] skipping advert")
		return nil
	}

	var events []*router.Event
	for _, event := range advert.Events {
		route := router.Route{
			Service: event.Route.Service,
			Address: event.Route.Address,
			Gateway: event.Route.Gateway,
			Network: event.Route.Network,
			Link:    event.Route.Link,
			Metric:  int(event.Route.Metric),
		}

		e := &router.Event{
			Type:      router.EventType(event.Type),
			Timestamp: time.Unix(0, advert.Timestamp),
			Route:     route,
		}

		events = append(events, e)
	}

	a := &router.Advert{
		Id:        advert.Id,
		Type:      router.AdvertType(advert.Type),
		Timestamp: time.Unix(0, advert.Timestamp),
		TTL:       time.Duration(advert.Ttl),
		Events:    events,
	}

	if err := s.router.Process(a); err != nil {
		return fmt.Errorf("[router] failed processing advert: %s", err)
	}

	return nil
}

// rtr is micro router
type rtr struct {
	// router is the micro router
	router.Router
	// publisher to publish router adverts
	micro.Publisher
}

// newRouter creates new micro router and returns it
func newRouter(service micro.Service, router router.Router) *rtr {
	s := &sub{
		router: router,
	}

	// register subscriber
	if err := micro.RegisterSubscriber(Topic, service.Server(), s); err != nil {
		log.Logf("[router] failed to subscribe to adverts: %s", err)
		os.Exit(1)
	}

	return &rtr{
		Router:    router,
		Publisher: micro.NewPublisher(Topic, service.Client()),
	}
}

// PublishAdverts publishes adverts for other routers to consume
func (r *rtr) PublishAdverts(ch <-chan *router.Advert) error {
	for advert := range ch {
		var events []*pb.Event
		for _, event := range advert.Events {
			route := &pb.Route{
				Service: event.Route.Service,
				Address: event.Route.Address,
				Gateway: event.Route.Gateway,
				Network: event.Route.Network,
				Link:    event.Route.Link,
				Metric:  int64(event.Route.Metric),
			}
			e := &pb.Event{
				Type:      pb.EventType(event.Type),
				Timestamp: event.Timestamp.UnixNano(),
				Route:     route,
			}
			events = append(events, e)
		}

		a := &pb.Advert{
			Id:        r.Options().Id,
			Type:      pb.AdvertType(advert.Type),
			Timestamp: advert.Timestamp.UnixNano(),
			Events:    events,
		}

		if err := r.Publish(context.Background(), a); err != nil {
			log.Logf("[router] error publishing advert: %v", err)
			return fmt.Errorf("error publishing advert: %v", err)
		}
	}

	return nil
}

// Start starts the micro router
func (r *rtr) Start() error {
	// start the router
	if err := r.Router.Start(); err != nil {
		return fmt.Errorf("failed to start router: %v", err)
	}

	return nil
}

// Stop stops the micro router
func (r *rtr) Stop() error {
	// stop the router
	if err := r.Router.Stop(); err != nil {
		return fmt.Errorf("failed to stop router: %v", err)
	}

	return nil
}

// run runs the micro server
func run(ctx *cli.Context, srvOpts ...micro.Option) {
	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	if len(ctx.GlobalString("server_name")) > 0 {
		Name = ctx.GlobalString("server_name")
	}
	if len(ctx.String("address")) > 0 {
		Address = ctx.String("address")
	}
	if len(ctx.String("router_address")) > 0 {
		Router = ctx.String("router")
	}
	if len(ctx.String("network_address")) > 0 {
		Network = ctx.String("network")
	}
	// default gateway address
	var gateway string
	if len(ctx.String("gateway_address")) > 0 {
		gateway = ctx.String("gateway")
	}

	// Initialise service
	service := micro.NewService(
		micro.Name(Name),
		micro.Address(Address),
		micro.RegisterTTL(time.Duration(ctx.GlobalInt("register_ttl"))*time.Second),
		micro.RegisterInterval(time.Duration(ctx.GlobalInt("register_interval"))*time.Second),
	)

	r := router.NewRouter(
		router.Id(service.Server().Options().Id),
		router.Address(Router),
		router.Network(Network),
		router.Registry(service.Client().Options().Registry),
		router.Gateway(gateway),
	)

	// register router handler
	pb.RegisterRouterHandler(
		service.Server(),
		&handler.Router{
			Router: r,
		},
	)

	// register the table handler
	pb.RegisterTableHandler(
		service.Server(),
		&handler.Table{
			Router: r,
		},
	)

	// create new micro router and start advertising routes
	rtr := newRouter(service, r)

	log.Log("[router] starting micro router")

	if err := rtr.Start(); err != nil {
		log.Logf("[router] failed to start: %s", err)
		os.Exit(1)
	}

	log.Log("[router] starting to advertise")

	advertChan, err := rtr.Advertise()
	if err != nil {
		log.Logf("[router] failed to advertise: %s", err)
		log.Log("[router] attempting to stop the router")
		if err := rtr.Stop(); err != nil {
			log.Logf("[router] failed to stop: %s", err)
			os.Exit(1)
		}
		os.Exit(1)
	}

	var wg sync.WaitGroup
	// error channel to collect router errors
	errChan := make(chan error, 2)

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- rtr.PublishAdverts(advertChan)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- service.Run()
	}()

	// we block here until either service or server fails
	if err := <-errChan; err != nil {
		log.Logf("[router] error running the router: %v", err)
	}

	log.Log("[router] attempting to stop the router")

	// stop the router
	if err := r.Stop(); err != nil {
		log.Logf("[router] failed to stop: %s", err)
		os.Exit(1)
	}

	wg.Wait()

	log.Logf("[router] successfully stopped")
}

func Commands(options ...micro.Option) []cli.Command {
	command := cli.Command{
		Name:  "router",
		Usage: "Run the micro network router",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:   "router_address",
				Usage:  "Set the micro router address :9093",
				EnvVar: "MICRO_ROUTER_ADDRESS",
			},
			cli.StringFlag{
				Name:   "network_address",
				Usage:  "Set the micro network address: local",
				EnvVar: "MICRO_NETWORK_ADDRESS",
			},
			cli.StringFlag{
				Name:   "gateway_address",
				Usage:  "Set the micro default gateway address :9094",
				EnvVar: "MICRO_GATEWAY_ADDRESS",
			},
		},
		Action: func(ctx *cli.Context) {
			run(ctx, options...)
		},
	}

	for _, p := range Plugins() {
		if cmds := p.Commands(); len(cmds) > 0 {
			command.Subcommands = append(command.Subcommands, cmds...)
		}

		if flags := p.Flags(); len(flags) > 0 {
			command.Flags = append(command.Flags, flags...)
		}
	}

	return []cli.Command{command}
}
<|endoftext|>


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

package rpc

import (
	"net"
	"testing"

	"github.com/cockroachdb/cockroach/util"
)

func TestInvalidAddrLength(t *testing.T) {
	testAddrs := []net.Addr{
		util.MakeRawAddr("tcp", "127.0.0.1:8080"),
		util.MakeRawAddr("tcp", "127.0.0.1:8081"),
		util.MakeRawAddr("tcp", "127.0.0.1:8082"),
	}

	testSendOption := Options{
		N: 5,
	}

	ret, _ := Send(testSendOption, "", testAddrs, nil, nil, nil)
	if ret != nil {
		t.Fatalf("Shorter addrs should have nil and SendError return")
	}
}
<commit_msg>modify testcase for rpc.Send()<commit_after>// Copyright 2015 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License. See the AUTHORS file
// for names of contributors.
//
// Author: joezxy (joe.zxy@foxmail.com)

package rpc

import (
	"testing"
)

func TestInvalidAddrLength(t *testing.T) {

	// The provided addrs is nil, so its length will be always
	// less than the specified response number
	ret, err := Send(Options{N: 1}, "", nil, nil, nil, nil)

	// the expected return is nil and SendError
	if _, ok := err.(SendError); !ok || ret != nil {
		t.Fatalf("Shorter addrs should return nil and SendError.")
	}
}
<|endoftext|>


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

// Package main contains a client which pulls messages from a subscription and prints them.
package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"golang.org/x/net/context"

	"google.golang.org/cloud/pubsub"
)

var (
	projID     = flag.String("p", "", "The ID of your Google Cloud project.")
	subName    = flag.String("s", "", "The name of the subscription to pull from")
	numConsume = flag.Int("n", 10, "The number of messages to consume")
)

func main() {
	flag.Parse()

	if *projID == "" {
		log.Fatal("-p is required")
	}
	if *subName == "" {
		log.Fatal("-s is required")
	}

	ctx := context.Background()

	client, err := pubsub.NewClient(ctx, *projID)
	if err != nil {
		log.Fatalf("creating pubsub client: %v", err)
	}

	sub := client.Subscription(*subName)

	it, err := sub.Pull(ctx, time.Hour)
	if err != nil {
		fmt.Printf("error constructing iterator: %v", err)
		return
	}

	for i := 0; i < *numConsume; i++ {
		m, err := it.Next(ctx)
		if err != nil {
			break
		}
		fmt.Printf("got message: %v\n", string(m.Data))
		m.Done(true)
	}

	it.Close()
	if err != nil {
		fmt.Printf("%v", err)
	}
}
<commit_msg>pubsub: unbreak consumer example.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main contains a client which pulls messages from a subscription and prints them.
package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"golang.org/x/net/context"

	"google.golang.org/cloud/pubsub"
)

var (
	projID     = flag.String("p", "", "The ID of your Google Cloud project.")
	subName    = flag.String("s", "", "The name of the subscription to pull from")
	numConsume = flag.Int("n", 10, "The number of messages to consume")
)

func main() {
	flag.Parse()

	if *projID == "" {
		log.Fatal("-p is required")
	}
	if *subName == "" {
		log.Fatal("-s is required")
	}

	ctx := context.Background()

	client, err := pubsub.NewClient(ctx, *projID)
	if err != nil {
		log.Fatalf("creating pubsub client: %v", err)
	}

	sub := client.Subscription(*subName)

	it, err := sub.Pull(ctx, time.Hour)
	if err != nil {
		fmt.Printf("error constructing iterator: %v", err)
		return
	}

	for i := 0; i < *numConsume; i++ {
		m, err := it.Next()
		if err != nil {
			fmt.Printf("advancing iterator: %v", err)
			break
		}
		fmt.Printf("got message: %v\n", string(m.Data))
		m.Done(true)
	}

	if err := it.Close(); err != nil {
		fmt.Printf("closing iterator: %v", err)
	}
}
<|endoftext|>


<commit_before>package instructions

import "jvmgo/rtda"

//type Ref *rtda.Obj

// Load reference from array
type aaload struct {NoOperandsInstruction}
func (self *aaload) execute(thread *rtda.Thread) {
    stack := thread.CurrentFrame().OperandStack()
    arrRef := popAndCheckArrRef(stack)
    index := int(stack.PopInt())

    refArr := arrRef.Fields().([]*rtda.Obj)
    ref := refArr[checkIndex(index, len(refArr))]
    stack.PushRef(ref)
}

// Load byte or boolean from array
type baload struct {NoOperandsInstruction}
func (self *baload) execute(thread *rtda.Thread) {
    stack := thread.CurrentFrame().OperandStack()
    arrRef := popAndCheckArrRef(stack)
    index := int(stack.PopInt())

    byteArr := arrRef.Fields().([]int8)
    val := byteArr[checkIndex(index, len(byteArr))]
    stack.PushInt(int32(val))
}

// Load char from array
type caload struct {NoOperandsInstruction}
func (self *caload) execute(thread *rtda.Thread) {
    // todo
}

// Load double from array
type daload struct {NoOperandsInstruction}
func (self *daload) execute(thread *rtda.Thread) {
    // todo
}

// Load float from array
type faload struct {NoOperandsInstruction}
func (self *faload) execute(thread *rtda.Thread) {
    // todo
}

// Load int from array
type iaload struct {NoOperandsInstruction}
func (self *iaload) execute(thread *rtda.Thread) {
    // todo
}

// Load long from array
type laload struct {NoOperandsInstruction}
func (self *laload) execute(thread *rtda.Thread) {
    // todo
}

// Load short from array
type saload struct {NoOperandsInstruction}
func (self *saload) execute(thread *rtda.Thread) {
    // todo
}

func popAndCheckArrRef(stack *rtda.OperandStack) (*rtda.Obj) {
    arrRef := stack.PopRef()
    if arrRef == nil {
        // todo
        panic("NullPointerException")
    }
    return arrRef
}

func checkIndex(index, len int) (int) {
    if index < 0 || index >= len {
        panic("ArrayIndexOutOfBoundsException")
    }
    return index
}
<commit_msg>code refactor<commit_after>package instructions

import "jvmgo/rtda"

//type Ref *rtda.Obj

// Load reference from array
type aaload struct {NoOperandsInstruction}
func (self *aaload) execute(thread *rtda.Thread) {
    stack, arrRef, index := popArrAndIndex(thread)
    refArr := arrRef.Fields().([]*rtda.Obj)
    ref := refArr[checkIndex(index, len(refArr))]
    stack.PushRef(ref)
}

// Load byte or boolean from array
type baload struct {NoOperandsInstruction}
func (self *baload) execute(thread *rtda.Thread) {
    stack, arrRef, index := popArrAndIndex(thread)
    byteArr := arrRef.Fields().([]int8)
    val := byteArr[checkIndex(index, len(byteArr))]
    stack.PushInt(int32(val))
}

// Load char from array
type caload struct {NoOperandsInstruction}
func (self *caload) execute(thread *rtda.Thread) {
    // todo
}

// Load double from array
type daload struct {NoOperandsInstruction}
func (self *daload) execute(thread *rtda.Thread) {
    // todo
}

// Load float from array
type faload struct {NoOperandsInstruction}
func (self *faload) execute(thread *rtda.Thread) {
    // todo
}

// Load int from array
type iaload struct {NoOperandsInstruction}
func (self *iaload) execute(thread *rtda.Thread) {
    // todo
}

// Load long from array
type laload struct {NoOperandsInstruction}
func (self *laload) execute(thread *rtda.Thread) {
    // todo
}

// Load short from array
type saload struct {NoOperandsInstruction}
func (self *saload) execute(thread *rtda.Thread) {
    // todo
}

func popArrAndIndex(thread *rtda.Thread) (*rtda.OperandStack, *rtda.Obj, int) {
    stack := thread.CurrentFrame().OperandStack()
    arrRef := stack.PopRef()
    index := int(stack.PopInt())
    if arrRef == nil {
        // todo
        panic("NullPointerException")
    }
    return stack, arrRef, index
}

func checkIndex(index, len int) (int) {
    if index < 0 || index >= len {
        panic("ArrayIndexOutOfBoundsException")
    }
    return index
}
<|endoftext|>


<commit_before>// query_benchmarker speed tests servers using requests from stdin.
//
// It reads encoded Query objects from stdin, and makes concurrent requests
// to the provided HTTP endpoint. This program has no knowledge of the
// internals of the endpoint.
//
// TODO(rw): On my machine, this only decodes 700k/sec messages from stdin.
package main

import (
	"bufio"
	"encoding/gob"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"
	"sort"
	"sync"
	"time"
)

// Program option vars:
var (
	daemonUrl            string
	workers              int
	debug                int
	prettyPrintResponses bool
	limit                int64
	printInterval        int64
	memProfile           string
)

// Global vars:
var (
	queryPool    sync.Pool
	queryChan    chan *Query
	statPool     sync.Pool
	statChan     chan *Stat
	workersGroup sync.WaitGroup
	statGroup    sync.WaitGroup
)

// Parse args:
func init() {
	flag.StringVar(&daemonUrl, "url", "http://localhost:8086", "Daemon URL.")
	flag.IntVar(&workers, "workers", 1, "Number of concurrent requests to make.")
	flag.IntVar(&debug, "debug", 0, "Whether to print debug messages.")
	flag.Int64Var(&limit, "limit", -1, "Limit the number of queries to send.")
	flag.Int64Var(&printInterval, "print-interval", 100, "Print timing stats to stderr after this many queries (0 to disable)")
	flag.BoolVar(&prettyPrintResponses, "print-responses", false, "Pretty print JSON response bodies (for correctness checking) (default false).")
	flag.StringVar(&memProfile, "memprofile", "", "Write a memory profile to this file.")

	flag.Parse()
}

func main() {
	// Make pools to minimize heap usage:
	queryPool = sync.Pool{
		New: func() interface{} {
			return &Query{
				HumanLabel:       make([]byte, 0, 1024),
				HumanDescription: make([]byte, 0, 1024),
				Method:           make([]byte, 0, 1024),
				Path:             make([]byte, 0, 1024),
				Body:             make([]byte, 0, 1024),
			}
		},
	}

	statPool = sync.Pool{
		New: func() interface{} {
			return &Stat{
				Label: make([]byte, 0, 1024),
				Value: 0.0,
			}
		},
	}

	// Make data and control channels:
	queryChan = make(chan *Query, workers)
	statChan = make(chan *Stat, workers)

	// Launch the stats processor:
	statGroup.Add(1)
	go processStats()

	// Launch the query processors:
	for i := 0; i < workers; i++ {
		workersGroup.Add(1)
		w := NewHTTPClient(daemonUrl, debug)
		go processQueries(w)
	}

	// Read in jobs, closing the job channel when done:
	input := bufio.NewReaderSize(os.Stdin, 1<<20)
	wallStart := time.Now()
	scan(input)
	close(queryChan)

	// Block for workers to finish sending requests, closing the stats
	// channel when done:
	workersGroup.Wait()
	close(statChan)

	// Wait on the stat collector to finish (and print its results):
	statGroup.Wait()

	wallEnd := time.Now()
	wallTook := wallEnd.Sub(wallStart)
	_, err := fmt.Printf("wall clock time: %fsec\n", float64(wallTook.Nanoseconds())/1e9)
	if err != nil {
		log.Fatal(err)
	}

	// (Optional) create a memory profile:
	if memProfile != "" {
		f, err := os.Create(memProfile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.WriteHeapProfile(f)
		f.Close()
	}
}

// scan reads encoded Queries and places them onto the workqueue.
func scan(r io.Reader) {
	dec := gob.NewDecoder(r)

	n := int64(0)
	for {
		if limit >= 0 && n >= limit {
			break
		}

		q := queryPool.Get().(*Query)
		err := dec.Decode(q)
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		q.ID = n

		queryChan <- q

		n++

	}
}

// processQueries reads byte buffers from queryChan and writes them to the
// target server, while tracking latency.
func processQueries(w *HTTPClient) {
	opts := &HTTPClientDoOptions{
		Debug:                debug,
		PrettyPrintResponses: prettyPrintResponses,
	}
	for q := range queryChan {
		lag, err := w.Do(q, opts)

		stat := statPool.Get().(*Stat)
		stat.Init(q.HumanLabel, lag)
		statChan <- stat

		queryPool.Put(q)
		if err != nil {
			log.Fatalf("Error during request: %s\n", err.Error())
		}
	}
	workersGroup.Done()
}

// processStats collects latency results, aggregating them into summary
// statistics. Optionally, they are printed to stderr at regular intervals.
func processStats() {
	const allQueriesLabel = "all queries"
	statMapping := map[string]*StatGroup{
		allQueriesLabel: &StatGroup{},
	}

	i := int64(0)
	for stat := range statChan {
		if _, ok := statMapping[string(stat.Label)]; !ok {
			statMapping[string(stat.Label)] = &StatGroup{}
		}

		statMapping[allQueriesLabel].Push(stat.Value)
		statMapping[string(stat.Label)].Push(stat.Value)

		statPool.Put(stat)

		i++

		// print stats to stderr (if printInterval is greater than zero):
		if printInterval > 0 && i > 0 && i%printInterval == 0 && (i < limit || limit < 0) {
			_, err := fmt.Fprintf(os.Stderr, "after %d queries with %d workers:\n", i, workers)
			if err != nil {
				log.Fatal(err)
			}
			fprintStats(os.Stderr, statMapping)
			_, err = fmt.Fprintf(os.Stderr, "\n")
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	// the final stats output goes to stdout:
	_, err := fmt.Printf("run complete after %d queries with %d workers:\n", i, workers)
	if err != nil {
		log.Fatal(err)
	}
	fprintStats(os.Stdout, statMapping)
	statGroup.Done()
}

// fprintStats pretty-prints stats to the given writer.
func fprintStats(w io.Writer, statGroups map[string]*StatGroup) {
	maxKeyLength := 0
	keys := make([]string, 0, len(statGroups))
	for k := range statGroups {
		if len(k) > maxKeyLength {
			maxKeyLength = len(k)
		}
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := statGroups[k]
		minRate := 1e3 / v.Min
		meanRate := 1e3 / v.Mean
		maxRate := 1e3 / v.Max
		paddedKey := fmt.Sprintf("%s", k)
		for len(paddedKey) < maxKeyLength {
			paddedKey += " "
		}
		_, err := fmt.Fprintf(w, "%s : min: %8.2fms (%7.2f/sec), mean: %8.2fms (%7.2f/sec), max: %7.2fms (%6.2f/sec), count: %8d, sum: %5.1fsec \n", paddedKey, v.Min, minRate, v.Mean, meanRate, v.Max, maxRate, v.Count, v.Sum/1e3)
		if err != nil {
			log.Fatal(err)
		}
	}

}
<commit_msg>Update package comment on influxdb query benchmarker.<commit_after>// query_benchmarker speed tests InfluxDB using requests from stdin.
//
// It reads encoded Query objects from stdin, and makes concurrent requests
// to the provided HTTP endpoint. This program has no knowledge of the
// internals of the endpoint.
//
// TODO(rw): On my machine, this only decodes 700k/sec messages from stdin.
package main

import (
	"bufio"
	"encoding/gob"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"
	"sort"
	"sync"
	"time"
)

// Program option vars:
var (
	daemonUrl            string
	workers              int
	debug                int
	prettyPrintResponses bool
	limit                int64
	printInterval        int64
	memProfile           string
)

// Global vars:
var (
	queryPool    sync.Pool
	queryChan    chan *Query
	statPool     sync.Pool
	statChan     chan *Stat
	workersGroup sync.WaitGroup
	statGroup    sync.WaitGroup
)

// Parse args:
func init() {
	flag.StringVar(&daemonUrl, "url", "http://localhost:8086", "Daemon URL.")
	flag.IntVar(&workers, "workers", 1, "Number of concurrent requests to make.")
	flag.IntVar(&debug, "debug", 0, "Whether to print debug messages.")
	flag.Int64Var(&limit, "limit", -1, "Limit the number of queries to send.")
	flag.Int64Var(&printInterval, "print-interval", 100, "Print timing stats to stderr after this many queries (0 to disable)")
	flag.BoolVar(&prettyPrintResponses, "print-responses", false, "Pretty print JSON response bodies (for correctness checking) (default false).")
	flag.StringVar(&memProfile, "memprofile", "", "Write a memory profile to this file.")

	flag.Parse()
}

func main() {
	// Make pools to minimize heap usage:
	queryPool = sync.Pool{
		New: func() interface{} {
			return &Query{
				HumanLabel:       make([]byte, 0, 1024),
				HumanDescription: make([]byte, 0, 1024),
				Method:           make([]byte, 0, 1024),
				Path:             make([]byte, 0, 1024),
				Body:             make([]byte, 0, 1024),
			}
		},
	}

	statPool = sync.Pool{
		New: func() interface{} {
			return &Stat{
				Label: make([]byte, 0, 1024),
				Value: 0.0,
			}
		},
	}

	// Make data and control channels:
	queryChan = make(chan *Query, workers)
	statChan = make(chan *Stat, workers)

	// Launch the stats processor:
	statGroup.Add(1)
	go processStats()

	// Launch the query processors:
	for i := 0; i < workers; i++ {
		workersGroup.Add(1)
		w := NewHTTPClient(daemonUrl, debug)
		go processQueries(w)
	}

	// Read in jobs, closing the job channel when done:
	input := bufio.NewReaderSize(os.Stdin, 1<<20)
	wallStart := time.Now()
	scan(input)
	close(queryChan)

	// Block for workers to finish sending requests, closing the stats
	// channel when done:
	workersGroup.Wait()
	close(statChan)

	// Wait on the stat collector to finish (and print its results):
	statGroup.Wait()

	wallEnd := time.Now()
	wallTook := wallEnd.Sub(wallStart)
	_, err := fmt.Printf("wall clock time: %fsec\n", float64(wallTook.Nanoseconds())/1e9)
	if err != nil {
		log.Fatal(err)
	}

	// (Optional) create a memory profile:
	if memProfile != "" {
		f, err := os.Create(memProfile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.WriteHeapProfile(f)
		f.Close()
	}
}

// scan reads encoded Queries and places them onto the workqueue.
func scan(r io.Reader) {
	dec := gob.NewDecoder(r)

	n := int64(0)
	for {
		if limit >= 0 && n >= limit {
			break
		}

		q := queryPool.Get().(*Query)
		err := dec.Decode(q)
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		q.ID = n

		queryChan <- q

		n++

	}
}

// processQueries reads byte buffers from queryChan and writes them to the
// target server, while tracking latency.
func processQueries(w *HTTPClient) {
	opts := &HTTPClientDoOptions{
		Debug:                debug,
		PrettyPrintResponses: prettyPrintResponses,
	}
	for q := range queryChan {
		lag, err := w.Do(q, opts)

		stat := statPool.Get().(*Stat)
		stat.Init(q.HumanLabel, lag)
		statChan <- stat

		queryPool.Put(q)
		if err != nil {
			log.Fatalf("Error during request: %s\n", err.Error())
		}
	}
	workersGroup.Done()
}

// processStats collects latency results, aggregating them into summary
// statistics. Optionally, they are printed to stderr at regular intervals.
func processStats() {
	const allQueriesLabel = "all queries"
	statMapping := map[string]*StatGroup{
		allQueriesLabel: &StatGroup{},
	}

	i := int64(0)
	for stat := range statChan {
		if _, ok := statMapping[string(stat.Label)]; !ok {
			statMapping[string(stat.Label)] = &StatGroup{}
		}

		statMapping[allQueriesLabel].Push(stat.Value)
		statMapping[string(stat.Label)].Push(stat.Value)

		statPool.Put(stat)

		i++

		// print stats to stderr (if printInterval is greater than zero):
		if printInterval > 0 && i > 0 && i%printInterval == 0 && (i < limit || limit < 0) {
			_, err := fmt.Fprintf(os.Stderr, "after %d queries with %d workers:\n", i, workers)
			if err != nil {
				log.Fatal(err)
			}
			fprintStats(os.Stderr, statMapping)
			_, err = fmt.Fprintf(os.Stderr, "\n")
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	// the final stats output goes to stdout:
	_, err := fmt.Printf("run complete after %d queries with %d workers:\n", i, workers)
	if err != nil {
		log.Fatal(err)
	}
	fprintStats(os.Stdout, statMapping)
	statGroup.Done()
}

// fprintStats pretty-prints stats to the given writer.
func fprintStats(w io.Writer, statGroups map[string]*StatGroup) {
	maxKeyLength := 0
	keys := make([]string, 0, len(statGroups))
	for k := range statGroups {
		if len(k) > maxKeyLength {
			maxKeyLength = len(k)
		}
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := statGroups[k]
		minRate := 1e3 / v.Min
		meanRate := 1e3 / v.Mean
		maxRate := 1e3 / v.Max
		paddedKey := fmt.Sprintf("%s", k)
		for len(paddedKey) < maxKeyLength {
			paddedKey += " "
		}
		_, err := fmt.Fprintf(w, "%s : min: %8.2fms (%7.2f/sec), mean: %8.2fms (%7.2f/sec), max: %7.2fms (%6.2f/sec), count: %8d, sum: %5.1fsec \n", paddedKey, v.Min, minRate, v.Mean, meanRate, v.Max, maxRate, v.Count, v.Sum/1e3)
		if err != nil {
			log.Fatal(err)
		}
	}

}
<|endoftext|>


<commit_before>package dagr

import (
	"encoding/json"
	"io"
	"sort"
	"sync"
	"time"
)

type Tags map[string]string

// Dup clones the Tags map, t. If t is nil, it returns nil.
func (t Tags) Dup() Tags {
	if t == nil {
		return nil
	}

	d := make(Tags, len(t))
	for name, tag := range t {
		d[name] = tag
	}
	return d
}

type Fields map[string]Field

// Dup clones the Fields map. If deep is true, it will also duplicate the fields held, creating new field instances,
// otherwise it retains its references to the Fields held by fs. If fs is nil, it returns nil.
func (fs Fields) Dup(deep bool) Fields {
	if fs == nil {
		return nil
	}

	d := make(Fields, len(fs))
	for name, field := range fs {
		if deep {
			field = field.Dup()
		}
		d[name] = field
	}
	return d
}

// Measurement defines the minimum interface for a measurement that could be passed to InfluxDB. All measurements must
// have a key and a minimum of one field. Tags are optional.
//
// Unless stated otherwise, the results of Tags and Fields are considered immutable.
type Measurement interface {
	GetKey() string
	GetTags() Tags
	GetFields() Fields
}

// TimeMeasurement is a measurement that has a known, known, fixed time. It can be considered a measurement that is
// fixed to a specific point in time. TimeMeasurements are not necessarily read-only and may, for example, return
// time.Now(). In general, it is better to not implement TimeMeasurement if your measurement is returning time.Now().
type TimeMeasurement interface {
	GetTime() time.Time

	Measurement
}

type fixedField struct {
	prefix []byte
	fields []fixedField
}

// Point is a single Measurement as understood by InfluxDB.
type Point struct {
	key        string
	tagOrder   []string
	fieldOrder []string
	tags       map[string]string
	fields     map[string]Field
	m          sync.RWMutex
}

var _ = Measurement((*Point)(nil))

// NewPoint allocates a new Point with the given key, tags, and fields. If key is empty, NewPoint panics. If fields is
// empty, the point cannot be written until it has at least one field.
func NewPoint(key string, tags Tags, fields Fields) *Point {
	if key == "" {
		panic("dagr.NewPoint: key is empty")
	}

	p := &Point{
		key:    key,
		tags:   make(map[string]string, len(tags)),
		fields: make(map[string]Field, len(fields)),
	}

	for name, tag := range tags {
		p.addTag(name, tag)
	}

	for name, field := range fields {
		p.addField(name, field)
	}

	return p
}

// WriteTo writes the point to the given writer, w. If an error occurs while building the point, it writes nothing and
// return an error. If the point has no fields, it returns the error ErrNoFields.
func (p *Point) WriteTo(w io.Writer) (int64, error) {
	buf := getBuffer(w)
	p.m.RLock()
	defer func() {
		p.m.RUnlock()
		putBuffer(buf)
	}()

	buf.WriteString(tagEscaper.Replace(p.key))
	writeTags(buf, p.tags, p.tagOrder)

	buf.WriteByte(' ')
	if err := writeFields(buf, p.fields, p.fieldOrder); err != nil {
		buf.Truncate(int(buf.head))
		return 0, err
	}

	buf.WriteByte(' ')
	writeTimestamp(buf, clock.Now())
	buf.WriteByte('\n')

	return buf.WriteTo(w)
}

// GetKey returns the point's key.
func (p *Point) GetKey() string {
	return p.key
}

// Compiled returns a compiled form of the point. The resulting Measurement is immutable except for its field values.
// New fields may not be added and it will not return a key, tags, or values. The compiled form of a point is only
// useful to improve write times on points when necessary. If the point has no fields, it returns nil, as the point is
// not valid to write.
func (p *Point) Compiled() Measurement {
	p.m.RLock()
	p.m.RUnlock()

	if len(p.fieldOrder) == 0 {
		return nil
	}
	return p.compile()
}

func (p *Point) compile() compiledPoint {
	var c compiledPoint
	buf := getBuffer(nil)
	defer putBuffer(buf)

	// Write key
	buf.WriteString(tagEscaper.Replace(p.key))
	// Write tags
	writeTags(buf, p.tags, p.tagOrder)
	c.lead = buf.Len()
	// Write field names
	var pre byte = ' '
	fields := make([]compiledField, len(p.fieldOrder))
	for i, name := range p.fieldOrder {
		field := p.fields[name]

		from := buf.Len()
		buf.WriteByte(pre)
		pre = ','

		buf.WriteString(tagEscaper.Replace(name))
		buf.WriteByte('=')

		to := buf.Len()
		if i == 0 {
			from = to
			c.lead = to
		}
		fields[i] = compiledField{from, to, field}
	}

	c.prefix = append([]byte(nil), buf.Bytes()...)
	c.fields = fields

	return c
}

// Tags

func (p *Point) addTag(name, value string) {
	_, exists := p.tags[name]
	p.tags[name] = value
	if exists {
		return
	}
	p.tagOrder = insertOrderedString(p.tagOrder, name)
}

// SetTag sets a tag on the point with the given name and value. If the value is empty, the tag is removed. If the name
// is empty, the call is a no-op. It is safe to call SetTag from concurrent goroutines.
func (p *Point) SetTag(name, value string) {
	if name == "" {
		return
	} else if value == "" {
		p.RemoveTag(name)
		return
	}

	p.m.Lock()
	defer p.m.Unlock()
	p.addTag(name, value)
}

// RemoveTag removes the tag with the given name from the point. If name is empty, the call is a no-op. It is safe to
// call from concurrent goroutines.
func (p *Point) RemoveTag(name string) {
	if name == "" {
		return
	}

	p.m.Lock()
	defer p.m.Unlock()

	if _, ok := p.tags[name]; !ok {
		// No tag
		return
	}

	delete(p.tags, name)
	for i, tname := range p.tagOrder {
		if name == tname {
			copy(p.tagOrder[i:], p.tagOrder[i+1:])
			p.tagOrder = p.tagOrder[:len(p.tagOrder)-1]
			break
		}
	}
}

// GetTags returns a copy of the point's tags as a map of names to values. Names and values are not escaped. It is safe
// to copy and modify the result of this method.
func (p *Point) GetTags() Tags {
	p.m.RLock()
	defer p.m.RUnlock()
	return Tags(p.tags).Dup()
}

// Fields

// insertOrderedString inserts str in the ordered slice of strings. It assumes that all elements of slice are unique,
// though this isn't necessarily important except that having non-unique names would result in Point having a memory
// leak.
func insertOrderedString(slice []string, str string) []string {
	n := len(slice)
	if idx := sort.SearchStrings(slice, str); idx < n {
		slice = append(slice, "")
		copy(slice[idx+1:], slice[idx:n])
		slice[idx] = str
	} else {
		slice = append(slice, str)
	}
	return slice
}

func (p *Point) addField(name string, value Field) {
	_, exists := p.fields[name]
	p.fields[name] = value
	if exists {
		return
	}
	p.fieldOrder = insertOrderedString(p.fieldOrder, name)
}

// SetField sets a field with the given name and value. If name is empty, the call is a no-op. If value is nil, it
// removes the field.
func (p *Point) SetField(name string, value Field) {
	if name == "" {
		return
	} else if value == nil {
		p.RemoveField(name)
		return
	}

	p.m.Lock()
	defer p.m.Unlock()
	p.addField(name, value)
}

// RemoveField removes a field with the given name. If name is empty, the call is a no-op. It is safe to call
// RemoveField from concurrent goroutines.
func (p *Point) RemoveField(name string) {
	if name == "" {
		return
	}

	p.m.Lock()
	defer p.m.Unlock()

	if _, ok := p.fields[name]; !ok {
		// No field
		return
	}

	delete(p.fields, name)
	for i, fname := range p.fieldOrder {
		if name == fname {
			copy(p.fieldOrder[i:], p.fieldOrder[i+1:])
			p.fieldOrder = p.fieldOrder[:len(p.fieldOrder)-1]
			break
		}
	}
}

// GetFields returns a map of the point's fields. This map is a copy of the point's state and may be modified without
// affecting the point. The fields themselves are those held by the point, however, and modifying them will modify the
// point's state.
func (p *Point) GetFields() Fields {
	p.m.RLock()
	defer p.m.RUnlock()
	return Fields(p.fields).Dup(false)
}

func (p *Point) MarshalJSON() ([]byte, error) {
	p.m.RLock()
	defer p.m.RUnlock()
	jsonPoint := struct {
		Key       string
		Timestamp int64 `json:",string"`
		Tags      jsonFields
		Fields    jsonFields
	}{
		p.key,
		clock.Now().UnixNano(),
		makeJSONFields(p.fields, p.fieldOrder),
		makeJSONTags(p.tags, p.tagOrder),
	}

	return json.Marshal(jsonPoint)
}
<commit_msg>Add Point.SetKey<commit_after>package dagr

import (
	"encoding/json"
	"io"
	"sort"
	"sync"
	"time"
)

type Tags map[string]string

// Dup clones the Tags map, t. If t is nil, it returns nil.
func (t Tags) Dup() Tags {
	if t == nil {
		return nil
	}

	d := make(Tags, len(t))
	for name, tag := range t {
		d[name] = tag
	}
	return d
}

type Fields map[string]Field

// Dup clones the Fields map. If deep is true, it will also duplicate the fields held, creating new field instances,
// otherwise it retains its references to the Fields held by fs. If fs is nil, it returns nil.
func (fs Fields) Dup(deep bool) Fields {
	if fs == nil {
		return nil
	}

	d := make(Fields, len(fs))
	for name, field := range fs {
		if deep {
			field = field.Dup()
		}
		d[name] = field
	}
	return d
}

// Measurement defines the minimum interface for a measurement that could be passed to InfluxDB. All measurements must
// have a key and a minimum of one field. Tags are optional.
//
// Unless stated otherwise, the results of Tags and Fields are considered immutable.
type Measurement interface {
	GetKey() string
	GetTags() Tags
	GetFields() Fields
}

// TimeMeasurement is a measurement that has a known, known, fixed time. It can be considered a measurement that is
// fixed to a specific point in time. TimeMeasurements are not necessarily read-only and may, for example, return
// time.Now(). In general, it is better to not implement TimeMeasurement if your measurement is returning time.Now().
type TimeMeasurement interface {
	GetTime() time.Time

	Measurement
}

type fixedField struct {
	prefix []byte
	fields []fixedField
}

// Point is a single Measurement as understood by InfluxDB.
type Point struct {
	key        string
	tagOrder   []string
	fieldOrder []string
	tags       map[string]string
	fields     map[string]Field
	m          sync.RWMutex
}

var _ = Measurement((*Point)(nil))

// NewPoint allocates a new Point with the given key, tags, and fields. If key is empty, NewPoint panics. If fields is
// empty, the point cannot be written until it has at least one field.
func NewPoint(key string, tags Tags, fields Fields) *Point {
	if key == "" {
		panic("dagr.NewPoint: key is empty")
	}

	p := &Point{
		key:    key,
		tags:   make(map[string]string, len(tags)),
		fields: make(map[string]Field, len(fields)),
	}

	for name, tag := range tags {
		p.addTag(name, tag)
	}

	for name, field := range fields {
		p.addField(name, field)
	}

	return p
}

// SetKey sets the point's key.
func (p *Point) SetKey(key string) {
	p.m.Lock()
	defer p.m.Unlock()

	p.key = key
}

// WriteTo writes the point to the given writer, w. If an error occurs while building the point, it writes nothing and
// return an error. If the point has no fields, it returns the error ErrNoFields.
func (p *Point) WriteTo(w io.Writer) (int64, error) {
	buf := getBuffer(w)
	p.m.RLock()
	defer func() {
		p.m.RUnlock()
		putBuffer(buf)
	}()

	buf.WriteString(tagEscaper.Replace(p.key))
	writeTags(buf, p.tags, p.tagOrder)

	buf.WriteByte(' ')
	if err := writeFields(buf, p.fields, p.fieldOrder); err != nil {
		buf.Truncate(int(buf.head))
		return 0, err
	}

	buf.WriteByte(' ')
	writeTimestamp(buf, clock.Now())
	buf.WriteByte('\n')

	return buf.WriteTo(w)
}

// GetKey returns the point's key.
func (p *Point) GetKey() string {
	p.m.RLock()
	defer p.m.RUnlock()
	return p.key
}

// Compiled returns a compiled form of the point. The resulting Measurement is immutable except for its field values.
// New fields may not be added and it will not return a key, tags, or values. The compiled form of a point is only
// useful to improve write times on points when necessary. If the point has no fields, it returns nil, as the point is
// not valid to write.
func (p *Point) Compiled() Measurement {
	p.m.RLock()
	p.m.RUnlock()

	if len(p.fieldOrder) == 0 {
		return nil
	}
	return p.compile()
}

func (p *Point) compile() compiledPoint {
	var c compiledPoint
	buf := getBuffer(nil)
	defer putBuffer(buf)

	// Write key
	buf.WriteString(tagEscaper.Replace(p.key))
	// Write tags
	writeTags(buf, p.tags, p.tagOrder)
	c.lead = buf.Len()
	// Write field names
	var pre byte = ' '
	fields := make([]compiledField, len(p.fieldOrder))
	for i, name := range p.fieldOrder {
		field := p.fields[name]

		from := buf.Len()
		buf.WriteByte(pre)
		pre = ','

		buf.WriteString(tagEscaper.Replace(name))
		buf.WriteByte('=')

		to := buf.Len()
		if i == 0 {
			from = to
			c.lead = to
		}
		fields[i] = compiledField{from, to, field}
	}

	c.prefix = append([]byte(nil), buf.Bytes()...)
	c.fields = fields

	return c
}

// Tags

func (p *Point) addTag(name, value string) {
	_, exists := p.tags[name]
	p.tags[name] = value
	if exists {
		return
	}
	p.tagOrder = insertOrderedString(p.tagOrder, name)
}

// SetTag sets a tag on the point with the given name and value. If the value is empty, the tag is removed. If the name
// is empty, the call is a no-op. It is safe to call SetTag from concurrent goroutines.
func (p *Point) SetTag(name, value string) {
	if name == "" {
		return
	} else if value == "" {
		p.RemoveTag(name)
		return
	}

	p.m.Lock()
	defer p.m.Unlock()
	p.addTag(name, value)
}

// RemoveTag removes the tag with the given name from the point. If name is empty, the call is a no-op. It is safe to
// call from concurrent goroutines.
func (p *Point) RemoveTag(name string) {
	if name == "" {
		return
	}

	p.m.Lock()
	defer p.m.Unlock()

	if _, ok := p.tags[name]; !ok {
		// No tag
		return
	}

	delete(p.tags, name)
	for i, tname := range p.tagOrder {
		if name == tname {
			copy(p.tagOrder[i:], p.tagOrder[i+1:])
			p.tagOrder = p.tagOrder[:len(p.tagOrder)-1]
			break
		}
	}
}

// GetTags returns a copy of the point's tags as a map of names to values. Names and values are not escaped. It is safe
// to copy and modify the result of this method.
func (p *Point) GetTags() Tags {
	p.m.RLock()
	defer p.m.RUnlock()
	return Tags(p.tags).Dup()
}

// Fields

// insertOrderedString inserts str in the ordered slice of strings. It assumes that all elements of slice are unique,
// though this isn't necessarily important except that having non-unique names would result in Point having a memory
// leak.
func insertOrderedString(slice []string, str string) []string {
	n := len(slice)
	if idx := sort.SearchStrings(slice, str); idx < n {
		slice = append(slice, "")
		copy(slice[idx+1:], slice[idx:n])
		slice[idx] = str
	} else {
		slice = append(slice, str)
	}
	return slice
}

func (p *Point) addField(name string, value Field) {
	_, exists := p.fields[name]
	p.fields[name] = value
	if exists {
		return
	}
	p.fieldOrder = insertOrderedString(p.fieldOrder, name)
}

// SetField sets a field with the given name and value. If name is empty, the call is a no-op. If value is nil, it
// removes the field.
func (p *Point) SetField(name string, value Field) {
	if name == "" {
		return
	} else if value == nil {
		p.RemoveField(name)
		return
	}

	p.m.Lock()
	defer p.m.Unlock()
	p.addField(name, value)
}

// RemoveField removes a field with the given name. If name is empty, the call is a no-op. It is safe to call
// RemoveField from concurrent goroutines.
func (p *Point) RemoveField(name string) {
	if name == "" {
		return
	}

	p.m.Lock()
	defer p.m.Unlock()

	if _, ok := p.fields[name]; !ok {
		// No field
		return
	}

	delete(p.fields, name)
	for i, fname := range p.fieldOrder {
		if name == fname {
			copy(p.fieldOrder[i:], p.fieldOrder[i+1:])
			p.fieldOrder = p.fieldOrder[:len(p.fieldOrder)-1]
			break
		}
	}
}

// GetFields returns a map of the point's fields. This map is a copy of the point's state and may be modified without
// affecting the point. The fields themselves are those held by the point, however, and modifying them will modify the
// point's state.
func (p *Point) GetFields() Fields {
	p.m.RLock()
	defer p.m.RUnlock()
	return Fields(p.fields).Dup(false)
}

func (p *Point) MarshalJSON() ([]byte, error) {
	p.m.RLock()
	defer p.m.RUnlock()
	jsonPoint := struct {
		Key       string
		Timestamp int64 `json:",string"`
		Tags      jsonFields
		Fields    jsonFields
	}{
		p.key,
		clock.Now().UnixNano(),
		makeJSONFields(p.fields, p.fieldOrder),
		makeJSONTags(p.tags, p.tagOrder),
	}

	return json.Marshal(jsonPoint)
}
<|endoftext|>


<commit_before>package safe

import (
	"github.com/bndw/pick/errors"
)

func (s *Safe) Add(name, username, password string) (*Account, error) {
	if _, exists := s.Accounts[name]; exists {
		return nil, &errors.AccountExists{}
	}

	account := NewAccount(name, username, password)
	s.Accounts[name] = account

	if err := s.save(); err != nil {
		return nil, err
	}

	return &account, nil
}
<commit_msg>Fix issue when generating a new password for an already existing account.<commit_after>package safe

import (
	"github.com/bndw/pick/errors"
)

func (s *Safe) Add(name, username, password string) (*Account, error) {
	if _, exists := s.Accounts[name]; exists {
		account := s.Accounts[name]
		return &account, &errors.AccountExists{}
	}

	account := NewAccount(name, username, password)
	s.Accounts[name] = account

	if err := s.save(); err != nil {
		return nil, err
	}

	return &account, nil
}
<|endoftext|>


<commit_before>// Author: slowpoke <mail plus git at slowpoke dot io>
// Repository: https://github.com/proxypoke/i3ipc
//
// This program is free software under the terms of the
// Do What The Fuck You Want To Public License.
// It comes without any warranty, to the extent permitted by
// applicable law. For a copy of the license, see COPYING or
// head to http://sam.zoy.org/wtfpl/COPYING.

package i3ipc

import (
	"encoding/json"
	"log"
)

// Type for subscribable events.
type EventType int32

// Enumeration of currently available event types.
const (
	I3WorkspaceEvent EventType = iota
	I3OutputEvent
	I3ModeEvent
	// private value used for setting up internal stuff in init()
	// The idea is that if there's a new type of event added to i3, it only
	// needs to be added here and in the payloads slice below, and the rest of
	// the code won't need to change.
	eventmax
)

// This slice is used to map event types to their string representation.
var payloads []string = []string{"workspace", "output", "mode"}

// Dynamically add an event type by defining a name for it. Just in case i3 adds
// a new one and this library hasn't been updated yet. Returns the EventType
// which gets assigned to it.
//
// XXX: If you use this to add more than one new event type, add them in the
// RIGHT ORDER. I hope this case never pops up (because that would mean that
// this library is severely outdated), but I thought I'd warn you anyways.
func AddEventType(name string) (type_ EventType) {
	payloads = append(payloads, name)
	return EventType(len(payloads) - 1)
}

// Event describes an event reply from i3.
type Event struct {
	Type EventType
	// "change" is the name of the single field of the JSON map that i3 sends
	// when an event occurs, describing what happened.
	Change string
}

// Struct for replies from subscribe messages.
type subscribeReply struct {
	Success bool
}

// Subscription related errors.
type SubscribeError string

func (self SubscribeError) Error() string {
	return string(self)
}

// Private subscribe function. Sets up the socket.
func (self *IPCSocket) subscribe(type_ EventType) (err error) {
	json_reply, err := self.Raw(I3Subscribe, "[\""+payloads[type_]+"\"]")
	if err != nil {
		return
	}

	var subs_reply subscribeReply
	err = json.Unmarshal(json_reply, &subs_reply)
	if err != nil {
		return
	}

	if !subs_reply.Success {
		// TODO: Better error description.
		err = SubscribeError("Could not subscribe.")
	}
	return
}

// Subscribe to an event type. Returns a channel from which events can be read.
func Subscribe(type_ EventType) (subs chan Event, err error) {
	if type_ >= eventmax || type_ < 0 {
		err = SubscribeError("No such event type.")
		return
	}
	subs = make(chan Event)
	eventSockets[type_].subscribers = append(
		eventSockets[type_].subscribers, subs)
	return
}

// Listen for events on this socket, multiplexing them to all subscribers.
//
// XXX: This will cause all messages which are not events to be DROPPED.
func (self *IPCSocket) listen() {
	for {
		if !self.open {
			break
		}
		msg, err := self.recv()
		// XXX: This ignores all errors. Maybe a FIXME, maybe not.
		if err != nil {
			continue
		}
		// Drop non-event messages.
		if !msg.IsEvent {
			continue
		}

		var event Event
		event.Type = EventType(msg.Type)
		err = json.Unmarshal(msg.Payload, &event)

		// Send each subscriber the event in a nonblocking manner.
		for _, subscriber := range self.subscribers {
			select {
			case subscriber <- event: // NOP
			default:
				// If the event can't be written, just ignore this
				// subscriber.
			}
		}
	}
}

var eventSockets []*IPCSocket

func init() {
	// Check whether we have as much payloads as we have event types. You know,
	// just in case I'm coding on my third Club-Mate at 0400 in the morning when
	// updating this lib.
	if len(payloads) != int(eventmax) {
		log.Fatalf("Too much or not enough payloads: got %d, expected %d.\n",
			len(payloads), int(eventmax))
	}

	// Set up an IPCSocket to receive events for every type of event.
	var ev EventType
	for ; ev < eventmax; ev++ {
		sock, err := GetIPCSocket()
		err = sock.subscribe(ev)
		if err != nil {
			log.Fatalf("Can't subscribe: %v", err)
		}
		go sock.listen()
		if err != nil {
			log.Fatalf("Can't set up event sockets: %v", err)
		}

		eventSockets = append(eventSockets, sock)
	}
}
<commit_msg>fix: check if the socket is getting opened<commit_after>// Author: slowpoke <mail plus git at slowpoke dot io>
// Repository: https://github.com/proxypoke/i3ipc
//
// This program is free software under the terms of the
// Do What The Fuck You Want To Public License.
// It comes without any warranty, to the extent permitted by
// applicable law. For a copy of the license, see COPYING or
// head to http://sam.zoy.org/wtfpl/COPYING.

package i3ipc

import (
	"encoding/json"
	"log"
)

// Type for subscribable events.
type EventType int32

// Enumeration of currently available event types.
const (
	I3WorkspaceEvent EventType = iota
	I3OutputEvent
	I3ModeEvent
	// private value used for setting up internal stuff in init()
	// The idea is that if there's a new type of event added to i3, it only
	// needs to be added here and in the payloads slice below, and the rest of
	// the code won't need to change.
	eventmax
)

// This slice is used to map event types to their string representation.
var payloads []string = []string{"workspace", "output", "mode"}

// Dynamically add an event type by defining a name for it. Just in case i3 adds
// a new one and this library hasn't been updated yet. Returns the EventType
// which gets assigned to it.
//
// XXX: If you use this to add more than one new event type, add them in the
// RIGHT ORDER. I hope this case never pops up (because that would mean that
// this library is severely outdated), but I thought I'd warn you anyways.
func AddEventType(name string) (type_ EventType) {
	payloads = append(payloads, name)
	return EventType(len(payloads) - 1)
}

// Event describes an event reply from i3.
type Event struct {
	Type EventType
	// "change" is the name of the single field of the JSON map that i3 sends
	// when an event occurs, describing what happened.
	Change string
}

// Struct for replies from subscribe messages.
type subscribeReply struct {
	Success bool
}

// Subscription related errors.
type SubscribeError string

func (self SubscribeError) Error() string {
	return string(self)
}

// Private subscribe function. Sets up the socket.
func (self *IPCSocket) subscribe(type_ EventType) (err error) {
	json_reply, err := self.Raw(I3Subscribe, "[\""+payloads[type_]+"\"]")
	if err != nil {
		return
	}

	var subs_reply subscribeReply
	err = json.Unmarshal(json_reply, &subs_reply)
	if err != nil {
		return
	}

	if !subs_reply.Success {
		// TODO: Better error description.
		err = SubscribeError("Could not subscribe.")
	}
	return
}

// Subscribe to an event type. Returns a channel from which events can be read.
func Subscribe(type_ EventType) (subs chan Event, err error) {
	if type_ >= eventmax || type_ < 0 {
		err = SubscribeError("No such event type.")
		return
	}
	subs = make(chan Event)
	eventSockets[type_].subscribers = append(
		eventSockets[type_].subscribers, subs)
	return
}

// Listen for events on this socket, multiplexing them to all subscribers.
//
// XXX: This will cause all messages which are not events to be DROPPED.
func (self *IPCSocket) listen() {
	for {
		if !self.open {
			break
		}
		msg, err := self.recv()
		// XXX: This ignores all errors. Maybe a FIXME, maybe not.
		if err != nil {
			continue
		}
		// Drop non-event messages.
		if !msg.IsEvent {
			continue
		}

		var event Event
		event.Type = EventType(msg.Type)
		err = json.Unmarshal(msg.Payload, &event)

		// Send each subscriber the event in a nonblocking manner.
		for _, subscriber := range self.subscribers {
			select {
			case subscriber <- event: // NOP
			default:
				// If the event can't be written, just ignore this
				// subscriber.
			}
		}
	}
}

var eventSockets []*IPCSocket

func init() {
	// Check whether we have as much payloads as we have event types. You know,
	// just in case I'm coding on my third Club-Mate at 0400 in the morning when
	// updating this lib.
	if len(payloads) != int(eventmax) {
		log.Fatalf("Too much or not enough payloads: got %d, expected %d.\n",
			len(payloads), int(eventmax))
	}

	// Set up an IPCSocket to receive events for every type of event.
	var ev EventType
	for ; ev < eventmax; ev++ {
		sock, err := GetIPCSocket()
		if err != nil {
			log.Fatalf("Can't get i3 socket. Please make sure i3 is running. %v.", err)
		}
		err = sock.subscribe(ev)
		if err != nil {
			log.Fatalf("Can't subscribe: %v", err)
		}
		go sock.listen()
		if err != nil {
			log.Fatalf("Can't set up event sockets: %v", err)
		}

		eventSockets = append(eventSockets, sock)
	}
}
<|endoftext|>