<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/jzipfler/htw-ava/exercise1"
	"github.com/jzipfler/htw-ava/filehandler"
	"github.com/jzipfler/htw-ava/server"
	"github.com/jzipfler/htw-ava/utils"
	"log"
	"os"
	"os/signal"
	"syscall"
)

var (
	loggingPrefix             string
	logFile                   string
	id                        int
	ipAddress                 string
	port                      int
	nodeListFile              string
	graphvizFile              string
	isController              bool
	allNodes                  map[int]server.NetworkServer
	neighbors                 map[int]server.NetworkServer
	messageToAllNeighborsSend bool

	//targetId      int //TODO: TMP for client / server testing
)

// The ini function is called before the main function is started.
// It is used to do some stuff that should be done before the rest
// of the application starts and on what they may depend on.
func init() {
	flag.StringVar(&nodeListFile, "nodeList", "path/to/nodeList.txt", "A file where nodes are defined as follows: \"ID IP_ADDR:PORT\"")
	flag.StringVar(&graphvizFile, "graphvizFile", "path/to/graphviz.{txt,dot}", "A graphviz-dot file written with undirected edges, for example: \"graph G { 1 -- 2; }\"")
	flag.IntVar(&id, "id", 1, "The if of the actual starting node.")
	flag.StringVar(&ipAddress, "ipAddress", "127.0.0.1", "The ip address of the actual starting node.")
	flag.IntVar(&port, "port", 15100, "The port of the actual starting node.")
	flag.StringVar(&loggingPrefix, "loggingPrefix", "LOGGING --> ", "This can be used to define which prefix the logger should use to print his messages.")
	flag.StringVar(&logFile, "logFile", "path/to/logfile.txt", "This parameter can be used to print the logging output to the given file.")
	flag.BoolVar(&isController, "isController", false, "Tell the node if he should act as controller or as independent node.")

	//TODO: TMP for client / server testing
	//flag.IntVar(&targetId, "targetId", 1, "The id from the server the message should be sent to. Must be != the id.")
}

// The main function is used when the programm is called / executed.
func main() {
	if len(os.Args) == 1 {
		flag.Usage()
		os.Exit(0)
	}
	flag.Parse()

	if nodeListFile == "path/to/nodeList.txt" {
		log.Fatalf("The nodeListFile is required.\n%s\n", utils.ERROR_FOOTER)
	}
	var readFromNodeListError error
	allNodes, readFromNodeListError = filehandler.CollectAllFromNodeListFile(nodeListFile)
	if readFromNodeListError != nil {
		log.Fatalf("%s\n%s\n", readFromNodeListError.Error(), utils.ERROR_FOOTER)
	} else {
		if len(allNodes) == 1 {
			log.Fatalf("There is only one node in the nodeList. Ther must be at least 2.\n%s\n", utils.ERROR_FOOTER)
		}
	}

	go signalHandler() // Handle CTRL-C signals
	utils.InitializeLogger(logFile, loggingPrefix)

	if isController {
		controllerNode := server.New()
		controllerNode.SetClientName("Controller")
		controllerNode.SetIpAddressAsString(ipAddress)
		controllerNode.SetPort(port)
		controllerNode.SetUsedProtocol("tcp")
		exercise1.StartController(controllerNode, allNodes)
	} else {
		if graphvizFile == "path/to/graphviz.{txt,dot}" {
			neighbors = exercise1.ChooseThreeNeighbors(id, allNodes)
		} else {
			var err error
			neighbors, err = filehandler.CollectNeighborsFromGraphvizFile(graphvizFile)
			if err != nil {
				utils.PrintMessage("An error occured during the reading of the graphviz file: " + err.Error())
				utils.PrintMessage("Choose three randam neighbors instead.")
				neighbors = exercise1.ChooseThreeNeighbors(id, allNodes)
			}
		}
		utils.PrintMessage(fmt.Sprintf("The following %d neighbors are chosen: %v", len(neighbors), neighbors))
		exercise1.StartIndependentNode(id, allNodes, neighbors)
	}
}

// The sinalHanlder function waits for a signal and catches it.
// If it is a SIGINT, the program exists with return code 0.
func signalHandler() {
	c := make(chan os.Signal, 1)
	// Signal für CTRL-C abfangen...
	signal.Notify(c, syscall.SIGINT)

	// foreach signal received
	for signal := range c {
		fmt.Println("\nSignal empfangen...")
		fmt.Println(signal.String())
		switch signal {
		case syscall.SIGINT:
			os.Exit(0)
		}
	}
}
<commit_msg>Added a flag for the content of the message but dont use it yet.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/jzipfler/htw-ava/exercise1"
	"github.com/jzipfler/htw-ava/filehandler"
	"github.com/jzipfler/htw-ava/server"
	"github.com/jzipfler/htw-ava/utils"
	"log"
	"os"
	"os/signal"
	"syscall"
)

var (
	loggingPrefix             string
	logFile                   string
	id                        int
	ipAddress                 string
	port                      int
	messageContent            string
	nodeListFile              string
	graphvizFile              string
	isController              bool
	allNodes                  map[int]server.NetworkServer
	neighbors                 map[int]server.NetworkServer
	messageToAllNeighborsSend bool

	//targetId      int //TODO: TMP for client / server testing
)

// The ini function is called before the main function is started.
// It is used to do some stuff that should be done before the rest
// of the application starts and on what they may depend on.
func init() {
	flag.StringVar(&nodeListFile, "nodeList", "path/to/nodeList.txt", "A file where nodes are defined as follows: \"ID IP_ADDR:PORT\"")
	flag.StringVar(&graphvizFile, "graphvizFile", "path/to/graphviz.{txt,dot}", "A graphviz-dot file written with undirected edges, for example: \"graph G { 1 -- 2; }\"")
	flag.IntVar(&id, "id", 1, "The if of the actual starting node.")
	flag.StringVar(&ipAddress, "ipAddress", "127.0.0.1", "The ip address of the actual starting node.")
	flag.IntVar(&port, "port", 15100, "The port of the actual starting node.")
	// Defining two flags that do the same but have different names.
	flag.StringVar(&messageContent, "messageContent", "This is a message", "The message content is the string that is sent to the other nodes.")
	flag.StringVar(&messageContent, "rumor", "The earth is a disc.", "The rumor that is sent to the other nodes.")
	flag.StringVar(&loggingPrefix, "loggingPrefix", "LOGGING --> ", "This can be used to define which prefix the logger should use to print his messages.")
	flag.StringVar(&logFile, "logFile", "path/to/logfile.txt", "This parameter can be used to print the logging output to the given file.")
	flag.BoolVar(&isController, "isController", false, "Tell the node if he should act as controller or as independent node.")

	//TODO: TMP for client / server testing
	//flag.IntVar(&targetId, "targetId", 1, "The id from the server the message should be sent to. Must be != the id.")
}

// The main function is used when the programm is called / executed.
func main() {
	if len(os.Args) == 1 {
		flag.Usage()
		os.Exit(0)
	}
	flag.Parse()

	if nodeListFile == "path/to/nodeList.txt" {
		log.Fatalf("The nodeListFile is required.\n%s\n", utils.ERROR_FOOTER)
	}
	var readFromNodeListError error
	allNodes, readFromNodeListError = filehandler.CollectAllFromNodeListFile(nodeListFile)
	if readFromNodeListError != nil {
		log.Fatalf("%s\n%s\n", readFromNodeListError.Error(), utils.ERROR_FOOTER)
	} else {
		if len(allNodes) == 1 {
			log.Fatalf("There is only one node in the nodeList. Ther must be at least 2.\n%s\n", utils.ERROR_FOOTER)
		}
	}

	go signalHandler() // Handle CTRL-C signals
	utils.InitializeLogger(logFile, loggingPrefix)

	if isController {
		controllerNode := server.New()
		controllerNode.SetClientName("Controller")
		controllerNode.SetIpAddressAsString(ipAddress)
		controllerNode.SetPort(port)
		controllerNode.SetUsedProtocol("tcp")
		exercise1.StartController(controllerNode, allNodes)
	} else {
		if graphvizFile == "path/to/graphviz.{txt,dot}" {
			neighbors = exercise1.ChooseThreeNeighbors(id, allNodes)
		} else {
			var err error
			neighbors, err = filehandler.CollectNeighborsFromGraphvizFile(graphvizFile)
			if err != nil {
				utils.PrintMessage("An error occured during the reading of the graphviz file: " + err.Error())
				utils.PrintMessage("Choose three randam neighbors instead.")
				neighbors = exercise1.ChooseThreeNeighbors(id, allNodes)
			}
		}
		utils.PrintMessage(fmt.Sprintf("The following %d neighbors are chosen: %v", len(neighbors), neighbors))
		exercise1.StartIndependentNode(id, allNodes, neighbors)
	}
}

// The sinalHanlder function waits for a signal and catches it.
// If it is a SIGINT, the program exists with return code 0.
func signalHandler() {
	c := make(chan os.Signal, 1)
	// Signal für CTRL-C abfangen...
	signal.Notify(c, syscall.SIGINT)

	// foreach signal received
	for signal := range c {
		fmt.Println("\nSignal empfangen...")
		fmt.Println(signal.String())
		switch signal {
		case syscall.SIGINT:
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package fritz

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

	"github.com/bpicode/fritzctl/httpread"
	"github.com/bpicode/fritzctl/logger"
)

// HomeAutomationAPI API definition, guided by
// https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AHA-HTTP-Interface.pdf.
type HomeAutomationAPI interface {
	ListDevices() (*Devicelist, error)
	NameToAinTable() (map[string]string, error)
	SwitchOn(ain string) (string, error)
	SwitchOff(ain string) (string, error)
	Toggle(ain string) (string, error)
	ApplyTemperature(value float64, ain string) (string, error)
}

// HomeAutomation creates a Fritz AHA API from a given client.
func HomeAutomation(client *Client) HomeAutomationAPI {
	return &ahaHTTP{client: client}
}

type ahaHTTP struct {
	client *Client
}

func (aha *ahaHTTP) getf(url string) func() (*http.Response, error) {
	return func() (*http.Response, error) {
		logger.Debug("GET", url)
		return aha.client.HTTPClient.Get(url)
	}
}

// ListDevices lists the basic data of the smart home devices.
func (aha *ahaHTTP) ListDevices() (*Devicelist, error) {
	url := aha.homeAutoSwitch().
		query("switchcmd", "getdevicelistinfos").
		build()
	var deviceList Devicelist
	errRead := httpread.ReadFullyXML(aha.getf(url), &deviceList)
	return &deviceList, errRead
}

// SwitchOn switches a device on. The device is identified by its AIN.
func (aha *ahaHTTP) SwitchOn(ain string) (string, error) {
	return aha.switchForAin(ain, "setswitchon")
}

// SwitchOff switches a device off. The device is identified by its AIN.
func (aha *ahaHTTP) SwitchOff(ain string) (string, error) {
	return aha.switchForAin(ain, "setswitchoff")
}

// Toggle toggles the on/off state of a device. The device is identified by its AIN.
func (aha *ahaHTTP) Toggle(ain string) (string, error) {
	url := aha.homeAutoSwitch().
		query("ain", ain).
		query("switchcmd", "setswitchtoggle").
		build()
	return httpread.ReadFullyString(aha.getf(url))
}

// ApplyTemperature sets the desired temperature on a "HKR" device. The device is identified by its AIN.
func (aha *ahaHTTP) ApplyTemperature(value float64, ain string) (string, error) {
	doubledValue := 2 * value
	rounded := round(doubledValue)
	url := aha.homeAutoSwitch().
		query("ain", ain).
		query("switchcmd", "sethkrtsoll").
		query("param", fmt.Sprintf("%d", rounded)).
		build()
	return httpread.ReadFullyString(aha.getf(url))
}

func (aha *ahaHTTP) switchForAin(ain, command string) (string, error) {
	url := aha.homeAutoSwitch().
		query("ain", ain).
		query("switchcmd", command).
		build()
	return httpread.ReadFullyString(aha.getf(url))
}

// NameToAinTable returns a lookup name -> AIN.
func (aha *ahaHTTP) NameToAinTable() (map[string]string, error) {
	devList, err := aha.ListDevices()
	if err != nil {
		return nil, err
	}
	devs := devList.Devices
	table := make(map[string]string, len(devs))
	for _, dev := range devs {
		table[dev.Name] = strings.Replace(dev.Identifier, " ", "", -1)
	}
	return table, nil
}

func (aha *ahaHTTP) homeAutoSwitch() fritzURLBuilder {
	return newURLBuilder(aha.client.Config).path(homeAutomationURI).query("sid", aha.client.SessionInfo.SID)
}

// round rounds a float64 value to an integer.
func round(v float64) int64 {
	return int64(v + 0.5)
}

<commit_msg>go fmt<commit_after>package fritz

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

	"github.com/bpicode/fritzctl/httpread"
	"github.com/bpicode/fritzctl/logger"
)

// HomeAutomationAPI API definition, guided by
// https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AHA-HTTP-Interface.pdf.
type HomeAutomationAPI interface {
	ListDevices() (*Devicelist, error)
	NameToAinTable() (map[string]string, error)
	SwitchOn(ain string) (string, error)
	SwitchOff(ain string) (string, error)
	Toggle(ain string) (string, error)
	ApplyTemperature(value float64, ain string) (string, error)
}

// HomeAutomation creates a Fritz AHA API from a given client.
func HomeAutomation(client *Client) HomeAutomationAPI {
	return &ahaHTTP{client: client}
}

type ahaHTTP struct {
	client *Client
}

func (aha *ahaHTTP) getf(url string) func() (*http.Response, error) {
	return func() (*http.Response, error) {
		logger.Debug("GET", url)
		return aha.client.HTTPClient.Get(url)
	}
}

// ListDevices lists the basic data of the smart home devices.
func (aha *ahaHTTP) ListDevices() (*Devicelist, error) {
	url := aha.homeAutoSwitch().
		query("switchcmd", "getdevicelistinfos").
		build()
	var deviceList Devicelist
	errRead := httpread.ReadFullyXML(aha.getf(url), &deviceList)
	return &deviceList, errRead
}

// SwitchOn switches a device on. The device is identified by its AIN.
func (aha *ahaHTTP) SwitchOn(ain string) (string, error) {
	return aha.switchForAin(ain, "setswitchon")
}

// SwitchOff switches a device off. The device is identified by its AIN.
func (aha *ahaHTTP) SwitchOff(ain string) (string, error) {
	return aha.switchForAin(ain, "setswitchoff")
}

// Toggle toggles the on/off state of a device. The device is identified by its AIN.
func (aha *ahaHTTP) Toggle(ain string) (string, error) {
	url := aha.homeAutoSwitch().
		query("ain", ain).
		query("switchcmd", "setswitchtoggle").
		build()
	return httpread.ReadFullyString(aha.getf(url))
}

// ApplyTemperature sets the desired temperature on a "HKR" device. The device is identified by its AIN.
func (aha *ahaHTTP) ApplyTemperature(value float64, ain string) (string, error) {
	doubledValue := 2 * value
	rounded := round(doubledValue)
	url := aha.homeAutoSwitch().
		query("ain", ain).
		query("switchcmd", "sethkrtsoll").
		query("param", fmt.Sprintf("%d", rounded)).
		build()
	return httpread.ReadFullyString(aha.getf(url))
}

func (aha *ahaHTTP) switchForAin(ain, command string) (string, error) {
	url := aha.homeAutoSwitch().
		query("ain", ain).
		query("switchcmd", command).
		build()
	return httpread.ReadFullyString(aha.getf(url))
}

// NameToAinTable returns a lookup name -> AIN.
func (aha *ahaHTTP) NameToAinTable() (map[string]string, error) {
	devList, err := aha.ListDevices()
	if err != nil {
		return nil, err
	}
	devs := devList.Devices
	table := make(map[string]string, len(devs))
	for _, dev := range devs {
		table[dev.Name] = strings.Replace(dev.Identifier, " ", "", -1)
	}
	return table, nil
}

func (aha *ahaHTTP) homeAutoSwitch() fritzURLBuilder {
	return newURLBuilder(aha.client.Config).path(homeAutomationURI).query("sid", aha.client.SessionInfo.SID)
}

// round rounds a float64 value to an integer.
func round(v float64) int64 {
	return int64(v + 0.5)
}
<|endoftext|>


<commit_before>package mains

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/mattn/go-isatty"
	"github.com/zetamatta/go-getch"

	"github.com/zetamatta/nyagos/alias"
	"github.com/zetamatta/nyagos/commands"
	"github.com/zetamatta/nyagos/completion"
	"github.com/zetamatta/nyagos/dos"
	"github.com/zetamatta/nyagos/history"
	"github.com/zetamatta/nyagos/lua"
	"github.com/zetamatta/nyagos/readline"
	"github.com/zetamatta/nyagos/shell"
)

var rxAnsiEscCode = regexp.MustCompile("\x1b[^a-zA-Z]*[a-zA-Z]")

var Stamp string
var Commit string
var Version string

func setTitle(s string) {
	fmt.Fprintf(readline.Console, "\x1B]0;%s\007", s)
}

func nyagosPrompt(L lua.Lua) int {
	title, title_err := L.ToString(2)
	if title_err == nil && title != "" {
		setTitle(title)
	} else if wd, wdErr := os.Getwd(); wdErr == nil {
		if flag, _ := dos.IsElevated(); flag {
			setTitle("(Admin) - " + wd)
		} else {
			setTitle("NYAGOS - " + wd)
		}
	} else {
		if flag, _ := dos.IsElevated(); flag {
			setTitle("(Admin)")
		} else {
			setTitle("NYAGOS")
		}
	}
	template, err := L.ToString(1)
	if err != nil {
		template = "[" + err.Error() + "]"
	}
	text := Format2Prompt(template)

	fmt.Fprint(readline.Console, text)

	text = rxAnsiEscCode.ReplaceAllString(text, "")
	lfPos := strings.LastIndex(text, "\n")
	if lfPos >= 0 {
		text = text[lfPos+1:]
	}
	L.PushInteger(lua.Integer(readline.GetStringWidth(text)))
	return 1
}

var prompt_hook lua.Object = lua.TGoFunction(nyagosPrompt)

func printPrompt(L lua.Lua) (int, error) {
	L.Push(prompt_hook)

	if !L.IsFunction(-1) {
		L.Pop(1)
		return 0, nil
	}
	L.PushString(os.Getenv("PROMPT"))
	if err := L.Call(1, 1); err != nil {
		return 0, err
	}
	length, lengthErr := L.ToInteger(-1)
	L.Pop(1)
	if lengthErr == nil {
		return length, nil
	} else {
		return 0, fmt.Errorf("nyagos.prompt: return-value(length) is invalid: %s", lengthErr.Error())
	}
}

var luaFilter lua.Object = lua.TNil{}

var appdatapath_ string

func AppDataDir() string {
	if appdatapath_ == "" {
		appdatapath_ = filepath.Join(os.Getenv("APPDATA"), "NYAOS_ORG")
		os.Mkdir(appdatapath_, 0777)
	}
	return appdatapath_
}

var default_history *history.Container

func doLuaFilter(L lua.Lua, line string) string {
	stackPos := L.GetTop()
	defer L.SetTop(stackPos)

	L.Push(luaFilter)
	if !L.IsFunction(-1) {
		return line
	}
	L.PushString(line)
	err := L.Call(1, 1)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return line
	}
	if !L.IsString(-1) {
		return line
	}
	line2, err2 := L.ToString(-1)
	if err2 != nil {
		fmt.Fprintln(os.Stderr, err2)
		return line
	}
	return line2
}

func onFork(cmd *shell.Cmd) error {
	L, ok := cmd.Tag.(lua.Lua)
	if !ok {
		return errors.New("could not get lua instance")
	}
	newL, err := NewLua()
	if err != nil {
		return err
	}
	err = L.CloneTo(newL)
	if err != nil {
		return err
	}
	cmd.Tag = newL
	return nil
}

func offFork(cmd *shell.Cmd) error {
	L, ok := cmd.Tag.(lua.Lua)
	if !ok {
		return errors.New("could not get lua instance")
	}
	return L.Close()
}

type MainStream struct {
	shell.Stream
	L lua.Lua
}

func (this *MainStream) ReadLine(ctx context.Context) (context.Context, string, error) {
	ctx = context.WithValue(ctx, lua.NoInstance, this.L)
	ctx = context.WithValue(ctx, history.NoInstance, default_history)
	ctx, line, err := this.Stream.ReadLine(ctx)
	if err != nil {
		return ctx, "", err
	}
	return ctx, doLuaFilter(this.L, line), nil
}

func Main() error {
	// for issue #155 & #158
	lua.NG_UPVALUE_NAME["prompter"] = struct{}{}

	shell.SetHook(func(ctx context.Context, it *shell.Cmd) (int, bool, error) {
		rc, done, err := commands.Exec(ctx, it)
		return rc, done, err
	})
	completion.AppendCommandLister(commands.AllNames)
	completion.AppendCommandLister(alias.AllNames)
	completion.HookToList = append(completion.HookToList, luaHookForComplete)

	dos.CoInitializeEx(0, dos.COINIT_MULTITHREADED)
	defer dos.CoUninitialize()

	getch.DisableCtrlC()

	commands.Init()
	alias.Init()

	// Lua extension
	L, err := NewLua()
	if err != nil {
		return err
	}
	defer L.Close()

	it := shell.New()
	it.Tag = L
	it.OnFork = onFork
	it.OffFork = offFork

	langEngine := func(fname string) ([]byte, error) {
		return runLua(it, L, fname)
	}
	shellEngine := func(fname string) error {
		fd, err := os.Open(fname)
		if err != nil {
			return err
		}
		stream1 := NewCmdStreamFile(fd)
		_, err = it.Loop(stream1)
		fd.Close()
		if err == io.EOF {
			return nil
		} else {
			return err
		}
	}

	script, err := optionParse(it, L)
	if err != nil {
		return err
	}

	if !isatty.IsTerminal(os.Stdin.Fd()) || script != nil {
		silentmode = true
	}

	if err := loadScripts(shellEngine, langEngine); err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
	}

	if script != nil {
		if err := script(); err != nil {
			if err != io.EOF {
				return err
			} else {
				return nil
			}
		}
	}

	backupHistory := default_history
	defer func() {
		default_history = backupHistory
	}()

	var stream1 shell.Stream
	if isatty.IsTerminal(os.Stdin.Fd()) {
		constream := NewCmdStreamConsole(
			func() (int, error) { return printPrompt(L) })
		stream1 = constream
		default_history = constream.History
	} else {
		stream1 = NewCmdStreamFile(os.Stdin)
	}

	_, err = it.Loop(&MainStream{stream1, L})

	return err
}
<commit_msg>Fix `main` commandline aborts when Ctrl-C received.<commit_after>package mains

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/mattn/go-isatty"
	"github.com/zetamatta/go-getch"

	"github.com/zetamatta/nyagos/alias"
	"github.com/zetamatta/nyagos/commands"
	"github.com/zetamatta/nyagos/completion"
	"github.com/zetamatta/nyagos/dos"
	"github.com/zetamatta/nyagos/history"
	"github.com/zetamatta/nyagos/lua"
	"github.com/zetamatta/nyagos/readline"
	"github.com/zetamatta/nyagos/shell"
)

var rxAnsiEscCode = regexp.MustCompile("\x1b[^a-zA-Z]*[a-zA-Z]")

var Stamp string
var Commit string
var Version string

func setTitle(s string) {
	fmt.Fprintf(readline.Console, "\x1B]0;%s\007", s)
}

func nyagosPrompt(L lua.Lua) int {
	title, title_err := L.ToString(2)
	if title_err == nil && title != "" {
		setTitle(title)
	} else if wd, wdErr := os.Getwd(); wdErr == nil {
		if flag, _ := dos.IsElevated(); flag {
			setTitle("(Admin) - " + wd)
		} else {
			setTitle("NYAGOS - " + wd)
		}
	} else {
		if flag, _ := dos.IsElevated(); flag {
			setTitle("(Admin)")
		} else {
			setTitle("NYAGOS")
		}
	}
	template, err := L.ToString(1)
	if err != nil {
		template = "[" + err.Error() + "]"
	}
	text := Format2Prompt(template)

	fmt.Fprint(readline.Console, text)

	text = rxAnsiEscCode.ReplaceAllString(text, "")
	lfPos := strings.LastIndex(text, "\n")
	if lfPos >= 0 {
		text = text[lfPos+1:]
	}
	L.PushInteger(lua.Integer(readline.GetStringWidth(text)))
	return 1
}

var prompt_hook lua.Object = lua.TGoFunction(nyagosPrompt)

func printPrompt(L lua.Lua) (int, error) {
	L.Push(prompt_hook)

	if !L.IsFunction(-1) {
		L.Pop(1)
		return 0, nil
	}
	L.PushString(os.Getenv("PROMPT"))
	if err := L.Call(1, 1); err != nil {
		return 0, err
	}
	length, lengthErr := L.ToInteger(-1)
	L.Pop(1)
	if lengthErr == nil {
		return length, nil
	} else {
		return 0, fmt.Errorf("nyagos.prompt: return-value(length) is invalid: %s", lengthErr.Error())
	}
}

var luaFilter lua.Object = lua.TNil{}

var appdatapath_ string

func AppDataDir() string {
	if appdatapath_ == "" {
		appdatapath_ = filepath.Join(os.Getenv("APPDATA"), "NYAOS_ORG")
		os.Mkdir(appdatapath_, 0777)
	}
	return appdatapath_
}

var default_history *history.Container

func doLuaFilter(L lua.Lua, line string) string {
	stackPos := L.GetTop()
	defer L.SetTop(stackPos)

	L.Push(luaFilter)
	if !L.IsFunction(-1) {
		return line
	}
	L.PushString(line)
	err := L.Call(1, 1)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return line
	}
	if !L.IsString(-1) {
		return line
	}
	line2, err2 := L.ToString(-1)
	if err2 != nil {
		fmt.Fprintln(os.Stderr, err2)
		return line
	}
	return line2
}

func onFork(cmd *shell.Cmd) error {
	L, ok := cmd.Tag.(lua.Lua)
	if !ok {
		return errors.New("could not get lua instance")
	}
	newL, err := NewLua()
	if err != nil {
		return err
	}
	err = L.CloneTo(newL)
	if err != nil {
		return err
	}
	cmd.Tag = newL
	return nil
}

func offFork(cmd *shell.Cmd) error {
	L, ok := cmd.Tag.(lua.Lua)
	if !ok {
		return errors.New("could not get lua instance")
	}
	return L.Close()
}

type MainStream struct {
	shell.Stream
	L lua.Lua
}

func (this *MainStream) ReadLine(ctx context.Context) (context.Context, string, error) {
	ctx = context.WithValue(ctx, lua.NoInstance, this.L)
	ctx = context.WithValue(ctx, history.NoInstance, default_history)
	ctx, line, err := this.Stream.ReadLine(ctx)
	if err != nil {
		return ctx, "", err
	}
	return ctx, doLuaFilter(this.L, line), nil
}

func Main() error {
	// for issue #155 & #158
	lua.NG_UPVALUE_NAME["prompter"] = struct{}{}

	shell.SetHook(func(ctx context.Context, it *shell.Cmd) (int, bool, error) {
		rc, done, err := commands.Exec(ctx, it)
		return rc, done, err
	})
	completion.AppendCommandLister(commands.AllNames)
	completion.AppendCommandLister(alias.AllNames)
	completion.HookToList = append(completion.HookToList, luaHookForComplete)

	dos.CoInitializeEx(0, dos.COINIT_MULTITHREADED)
	defer dos.CoUninitialize()

	getch.DisableCtrlC()

	commands.Init()
	alias.Init()

	// Lua extension
	L, err := NewLua()
	if err != nil {
		return err
	}
	defer L.Close()

	it := shell.New()
	it.Tag = L
	it.OnFork = onFork
	it.OffFork = offFork

	langEngine := func(fname string) ([]byte, error) {
		return runLua(it, L, fname)
	}
	shellEngine := func(fname string) error {
		fd, err := os.Open(fname)
		if err != nil {
			return err
		}
		stream1 := NewCmdStreamFile(fd)
		_, err = it.Loop(stream1)
		fd.Close()
		if err == io.EOF {
			return nil
		} else {
			return err
		}
	}

	script, err := optionParse(it, L)
	if err != nil {
		return err
	}

	if !isatty.IsTerminal(os.Stdin.Fd()) || script != nil {
		silentmode = true
	}

	if err := loadScripts(shellEngine, langEngine); err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
	}

	if script != nil {
		if err := script(); err != nil {
			if err != io.EOF {
				return err
			} else {
				return nil
			}
		}
	}

	backupHistory := default_history
	defer func() {
		default_history = backupHistory
	}()

	var stream1 shell.Stream
	if isatty.IsTerminal(os.Stdin.Fd()) {
		constream := NewCmdStreamConsole(
			func() (int, error) { return printPrompt(L) })
		stream1 = constream
		default_history = constream.History
	} else {
		stream1 = NewCmdStreamFile(os.Stdin)
	}

	for {
		_, err = it.Loop(&MainStream{stream1, L})
		if err == io.EOF {
			return err
		}
		if err != nil {
			fmt.Println(err.Error())
		}
	}
}
<|endoftext|>


<commit_before>package brightbox

import (
	"net/url"
	"regexp"
	"time"
)

// Server represents a Cloud Server
// https://api.gb1.brightbox.com/1.0/#server
type Server struct {
	Id        string
	Name      string
	Status    string
	Locked    bool
	Hostname  string
	Fqdn      string
	CreatedAt *time.Time `json:"created_at"`
	// DeletedAt is nil if the server has not yet been deleted
	DeletedAt         *time.Time `json:"deleted_at"`
	ServerType        ServerType `json:"server_type"`
	CompatibilityMode bool       `json:"compatibility_mode"`
	Account           Account
	Zone              Zone
	Image             Image
	CloudIPs          []CloudIP `json:"cloud_ips"`
	Interfaces        []ServerInterface
	Snapshots         []Image
	ServerGroups      []ServerGroup `json:"server_groups"`
	ServerConsole
}

// ServerConsole is embedded into Server and contains the fields used in reponse
// to an ActivateConsoleForServer request.
type ServerConsole struct {
	ConsoleToken        string     `json:"console_token"`
	ConsoleUrl          string     `json:"console_url"`
	ConsoleTokenExpires *time.Time `json:"console_token_expires"`
}

// ServerOptions is used in conjunction with CreateServer and UpdateServer to
// create and update servers.
type ServerOptions struct {
	Id                string    `json:"-"`
	Image             string    `json:"image,omitempty"`
	Name              *string   `json:"name,omitempty"`
	ServerType        string    `json:"server_type,omitempty"`
	Zone              string    `json:"zone,omitempty"`
	UserData          *string   `json:"user_data,omitempty"`
	ServerGroups      *[]string `json:"server_groups,omitempty"`
	CompatibilityMode *bool     `json:"compatibility_mode,omitempty"`
}

// ServerInterface represent a server's network interface(s)
type ServerInterface struct {
	Id          string
	MacAddress  string `json:"mac_address"`
	IPv4Address string `json:"ipv4_address"`
	IPv6Address string `json:"ipv6_address"`
}

// Servers retrieves a list of all servers
func (c *Client) Servers() ([]Server, error) {
	var servers []Server
	_, err := c.MakeApiRequest("GET", "/1.0/servers", nil, &servers)
	if err != nil {
		return nil, err
	}
	return servers, err
}

// Server retrieves a detailed view of one server
func (c *Client) Server(identifier string) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("GET", "/1.0/servers/"+identifier, nil, server)
	if err != nil {
		return nil, err
	}
	return server, err
}

// CreateServer creates a new server.
//
// It takes a ServerOptions struct which requires, at minimum, a valid Image
// identifier. Not all attributes can be specified at create time (such as Id,
// which is allocated for you)
func (c *Client) CreateServer(newServer *ServerOptions) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("POST", "/1.0/servers", newServer, &server)
	if err != nil {
		return nil, err
	}
	return server, nil
}

// UpdateServer updates an existing server's attributes. Not all attributes can
// be changed after creation time (such as Image, ServerType and Zone).
//
// Specify the server you want to update using the ServerOptions Id field
func (c *Client) UpdateServer(updateServer *ServerOptions) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("PUT", "/1.0/servers/"+updateServer.Id, updateServer, &server)
	if err != nil {
		return nil, err
	}
	return server, nil
}

// DestroyServer issues a request to destroy the server
func (c *Client) DestroyServer(identifier string) error {
	_, err := c.MakeApiRequest("DELETE", "/1.0/servers/"+identifier, nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// StopServer issues a request to stop ("power off") an existing server
func (c *Client) StopServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/stop", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// StartServer issues a request to start ("power on") an existing server
func (c *Client) StartServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/start", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// RebootServer issues a request to reboot ("ctrl+alt+delete") an existing
// server
func (c *Client) RebootServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/reboot", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// ResetServer issues a request to reset ("power cycle") an existing server
func (c *Client) ResetServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/reset", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// ShutdownServer issues a request to shut down ("tap the power button") an
// existing server
func (c *Client) ShutdownServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/shutdown", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// LockServer locks an existing server, preventing it's destruction without
// first unlocking
func (c *Client) LockServer(identifier string) error {
	_, err := c.MakeApiRequest("PUT", "/1.0/servers/"+identifier+"/lock_resource", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// UnlockServer unlocks a previously locked existing server, allowing
// destruction again
func (c *Client) UnlockServer(identifier string) error {
	_, err := c.MakeApiRequest("PUT", "/1.0/servers/"+identifier+"/unlock_resource", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// SnapshotServer issues a request to snapshot the disk of an existing
// server. The snapshot is allocated an Image Id which is returned within an
// instance of Image.
func (c *Client) SnapshotServer(identifier string) (*Image, error) {
	res, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/snapshot", nil, nil)
	if err != nil {
		return nil, err
	}
	re := regexp.MustCompile("img-.....")
	imageId := re.FindString(res.Header.Get("Link"))
	if imageId != "" {
		img := new(Image)
		img.Id = imageId
		return img, nil
	}
	return nil, nil
}

// ActivateConsoleForServer issues a request to enable the graphical console for
// an existing server. The temporarily allocated ConsoleUrl, ConsoleToken and
// ConsoleTokenExpires data are returned within an instance of Server.
func (c *Client) ActivateConsoleForServer(identifier string) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/activate_console", nil, server)
	if err != nil {
		return nil, err
	}
	return server, nil
}

// FullConsoleUrl returns the console url for the server with the token in the
// query string.  Server needs a ConsoleUrl and ConsoleToken, retrieved using
// ActivateConsoleForServer
func (s *Server) FullConsoleUrl() string {
	if s.ConsoleUrl == "" || s.ConsoleToken == "" {
		return s.ConsoleUrl
	}
	u, err := url.Parse(s.ConsoleUrl)
	if u == nil || err != nil {
		return s.ConsoleUrl
	}
	values := u.Query()
	if values.Get("password") != "" {
		return s.ConsoleUrl
	}
	values.Set("password", s.ConsoleToken)
	u.RawQuery = values.Encode()
	return u.String()
}
<commit_msg>Have Lock/UnlockServer use Lock/UnlockResource<commit_after>package brightbox

import (
	"net/url"
	"regexp"
	"time"
)

// Server represents a Cloud Server
// https://api.gb1.brightbox.com/1.0/#server
type Server struct {
	Id        string
	Name      string
	Status    string
	Locked    bool
	Hostname  string
	Fqdn      string
	CreatedAt *time.Time `json:"created_at"`
	// DeletedAt is nil if the server has not yet been deleted
	DeletedAt         *time.Time `json:"deleted_at"`
	ServerType        ServerType `json:"server_type"`
	CompatibilityMode bool       `json:"compatibility_mode"`
	Account           Account
	Zone              Zone
	Image             Image
	CloudIPs          []CloudIP `json:"cloud_ips"`
	Interfaces        []ServerInterface
	Snapshots         []Image
	ServerGroups      []ServerGroup `json:"server_groups"`
	ServerConsole
}

// ServerConsole is embedded into Server and contains the fields used in reponse
// to an ActivateConsoleForServer request.
type ServerConsole struct {
	ConsoleToken        string     `json:"console_token"`
	ConsoleUrl          string     `json:"console_url"`
	ConsoleTokenExpires *time.Time `json:"console_token_expires"`
}

// ServerOptions is used in conjunction with CreateServer and UpdateServer to
// create and update servers.
type ServerOptions struct {
	Id                string    `json:"-"`
	Image             string    `json:"image,omitempty"`
	Name              *string   `json:"name,omitempty"`
	ServerType        string    `json:"server_type,omitempty"`
	Zone              string    `json:"zone,omitempty"`
	UserData          *string   `json:"user_data,omitempty"`
	ServerGroups      *[]string `json:"server_groups,omitempty"`
	CompatibilityMode *bool     `json:"compatibility_mode,omitempty"`
}

// ServerInterface represent a server's network interface(s)
type ServerInterface struct {
	Id          string
	MacAddress  string `json:"mac_address"`
	IPv4Address string `json:"ipv4_address"`
	IPv6Address string `json:"ipv6_address"`
}

// Servers retrieves a list of all servers
func (c *Client) Servers() ([]Server, error) {
	var servers []Server
	_, err := c.MakeApiRequest("GET", "/1.0/servers", nil, &servers)
	if err != nil {
		return nil, err
	}
	return servers, err
}

// Server retrieves a detailed view of one server
func (c *Client) Server(identifier string) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("GET", "/1.0/servers/"+identifier, nil, server)
	if err != nil {
		return nil, err
	}
	return server, err
}

// CreateServer creates a new server.
//
// It takes a ServerOptions struct which requires, at minimum, a valid Image
// identifier. Not all attributes can be specified at create time (such as Id,
// which is allocated for you)
func (c *Client) CreateServer(newServer *ServerOptions) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("POST", "/1.0/servers", newServer, &server)
	if err != nil {
		return nil, err
	}
	return server, nil
}

// UpdateServer updates an existing server's attributes. Not all attributes can
// be changed after creation time (such as Image, ServerType and Zone).
//
// Specify the server you want to update using the ServerOptions Id field
func (c *Client) UpdateServer(updateServer *ServerOptions) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("PUT", "/1.0/servers/"+updateServer.Id, updateServer, &server)
	if err != nil {
		return nil, err
	}
	return server, nil
}

// DestroyServer issues a request to destroy the server
func (c *Client) DestroyServer(identifier string) error {
	_, err := c.MakeApiRequest("DELETE", "/1.0/servers/"+identifier, nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// StopServer issues a request to stop ("power off") an existing server
func (c *Client) StopServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/stop", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// StartServer issues a request to start ("power on") an existing server
func (c *Client) StartServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/start", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// RebootServer issues a request to reboot ("ctrl+alt+delete") an existing
// server
func (c *Client) RebootServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/reboot", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// ResetServer issues a request to reset ("power cycle") an existing server
func (c *Client) ResetServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/reset", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// ShutdownServer issues a request to shut down ("tap the power button") an
// existing server
func (c *Client) ShutdownServer(identifier string) error {
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/shutdown", nil, nil)
	if err != nil {
		return err
	}
	return nil
}

// LockServer locks an existing server, preventing it's destruction without
// first unlocking. Deprecated, use LockResource instead.
func (c *Client) LockServer(identifier string) error {
	return c.LockResource(Server{Id: identifier})
}

// UnlockServer unlocks a previously locked existing server, allowing
// destruction again. Deprecated, use UnLockResource instead.
func (c *Client) UnlockServer(identifier string) error {
	return c.UnLockResource(Server{Id: identifier})
}

// SnapshotServer issues a request to snapshot the disk of an existing
// server. The snapshot is allocated an Image Id which is returned within an
// instance of Image.
func (c *Client) SnapshotServer(identifier string) (*Image, error) {
	res, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/snapshot", nil, nil)
	if err != nil {
		return nil, err
	}
	re := regexp.MustCompile("img-.....")
	imageId := re.FindString(res.Header.Get("Link"))
	if imageId != "" {
		img := new(Image)
		img.Id = imageId
		return img, nil
	}
	return nil, nil
}

// ActivateConsoleForServer issues a request to enable the graphical console for
// an existing server. The temporarily allocated ConsoleUrl, ConsoleToken and
// ConsoleTokenExpires data are returned within an instance of Server.
func (c *Client) ActivateConsoleForServer(identifier string) (*Server, error) {
	server := new(Server)
	_, err := c.MakeApiRequest("POST", "/1.0/servers/"+identifier+"/activate_console", nil, server)
	if err != nil {
		return nil, err
	}
	return server, nil
}

// FullConsoleUrl returns the console url for the server with the token in the
// query string.  Server needs a ConsoleUrl and ConsoleToken, retrieved using
// ActivateConsoleForServer
func (s *Server) FullConsoleUrl() string {
	if s.ConsoleUrl == "" || s.ConsoleToken == "" {
		return s.ConsoleUrl
	}
	u, err := url.Parse(s.ConsoleUrl)
	if u == nil || err != nil {
		return s.ConsoleUrl
	}
	values := u.Query()
	if values.Get("password") != "" {
		return s.ConsoleUrl
	}
	values.Set("password", s.ConsoleToken)
	u.RawQuery = values.Encode()
	return u.String()
}
<|endoftext|>


<commit_before>//   Copyright 2016 DigitalOcean
//
//   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 collectors

import (
	"encoding/json"
	"errors"
	"log"

	"github.com/prometheus/client_golang/prometheus"
)

// PoolUsageCollector displays statistics about each pool we have created
// in the ceph cluster.
type PoolUsageCollector struct {
	conn Conn

	// UsedBytes tracks the amount of bytes currently allocated for the pool. This
	// does not factor in the overcommitment made for individual images.
	UsedBytes *prometheus.GaugeVec

	// RawUsedBytes tracks the amount of raw bytes currently used for the pool. This
	// factors in the replication factor (size) of the pool.
	RawUsedBytes *prometheus.GaugeVec

	// MaxAvail tracks the amount of bytes currently free for the pool,
	// which depends on the replication settings for the pool in question.
	MaxAvail *prometheus.GaugeVec

	// Objects shows the no. of RADOS objects created within the pool.
	Objects *prometheus.GaugeVec

	// DirtyObjects shows the no. of RADOS dirty objects in a cache-tier pool,
	// this doesn't make sense in a regular pool, see:
	// http://lists.ceph.com/pipermail/ceph-users-ceph.com/2015-April/000557.html
	DirtyObjects *prometheus.GaugeVec

	// ReadIO tracks the read IO calls made for the images within each pool.
	ReadIO *prometheus.GaugeVec

	// Readbytes tracks the read throughput made for the images within each pool.
	ReadBytes *prometheus.GaugeVec

	// WriteIO tracks the write IO calls made for the images within each pool.
	WriteIO *prometheus.GaugeVec

	// WriteBytes tracks the write throughput made for the images within each pool.
	WriteBytes *prometheus.GaugeVec
}

// NewPoolUsageCollector creates a new instance of PoolUsageCollector and returns
// its reference.
func NewPoolUsageCollector(conn Conn, cluster string) *PoolUsageCollector {
	var (
		subSystem = "pool"
		poolLabel = []string{"pool"}
	)

	labels := make(prometheus.Labels)
	labels["cluster"] = cluster

	return &PoolUsageCollector{
		conn: conn,

		UsedBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "used_bytes",
				Help:        "Capacity of the pool that is currently under use",
				ConstLabels: labels,
			},
			poolLabel,
		),
		RawUsedBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "raw_used_bytes",
				Help:        "Raw capacity of the pool that is currently under use, this factors in the size",
				ConstLabels: labels,
			},
			poolLabel,
		),
		MaxAvail: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "available_bytes",
				Help:        "Free space for this ceph pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		Objects: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "objects_total",
				Help:        "Total no. of objects allocated within the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		DirtyObjects: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "dirty_objects_total",
				Help:        "Total no. of dirty objects in a cache-tier pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		ReadIO: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "read_total",
				Help:        "Total read i/o calls for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		ReadBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "read_bytes_total",
				Help:        "Total read throughput for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		WriteIO: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "write_total",
				Help:        "Total write i/o calls for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		WriteBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "write_bytes_total",
				Help:        "Total write throughput for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
	}
}

func (p *PoolUsageCollector) collectorList() []prometheus.Collector {
	return []prometheus.Collector{
		p.UsedBytes,
		p.RawUsedBytes,
		p.MaxAvail,
		p.Objects,
		p.DirtyObjects,
		p.ReadIO,
		p.ReadBytes,
		p.WriteIO,
		p.WriteBytes,
	}
}

type cephPoolStats struct {
	Pools []struct {
		Name  string `json:"name"`
		ID    int    `json:"id"`
		Stats struct {
			BytesUsed    float64 `json:"bytes_used"`
			RawBytesUsed float64 `json:"raw_bytes_used"`
			MaxAvail     float64 `json:"max_avail"`
			Objects      float64 `json:"objects"`
			DirtyObjects float64 `json:"dirty"`
			ReadIO       float64 `json:"rd"`
			ReadBytes    float64 `json:"rd_bytes"`
			WriteIO      float64 `json:"wr"`
			WriteBytes   float64 `json:"wr_bytes"`
		} `json:"stats"`
	} `json:"pools"`
}

func (p *PoolUsageCollector) collect() error {
	cmd := p.cephUsageCommand()
	buf, _, err := p.conn.MonCommand(cmd)
	if err != nil {
		return err
	}

	stats := &cephPoolStats{}
	if err := json.Unmarshal(buf, stats); err != nil {
		return err
	}

	if len(stats.Pools) < 1 {
		return errors.New("no pools found in the cluster to report stats on")
	}

	for _, pool := range stats.Pools {
		p.UsedBytes.WithLabelValues(pool.Name).Set(pool.Stats.BytesUsed)
		p.RawUsedBytes.WithLabelValues(pool.Name).Set(pool.Stats.RawBytesUsed)
		p.MaxAvail.WithLabelValues(pool.Name).Set(pool.Stats.MaxAvail)
		p.Objects.WithLabelValues(pool.Name).Set(pool.Stats.Objects)
		p.DirtyObjects.WithLabelValues(pool.Name).Set(pool.Stats.DirtyObjects)
		p.ReadIO.WithLabelValues(pool.Name).Set(pool.Stats.ReadIO)
		p.ReadBytes.WithLabelValues(pool.Name).Set(pool.Stats.ReadBytes)
		p.WriteIO.WithLabelValues(pool.Name).Set(pool.Stats.WriteIO)
		p.WriteBytes.WithLabelValues(pool.Name).Set(pool.Stats.WriteBytes)
	}

	return nil
}

func (p *PoolUsageCollector) cephUsageCommand() []byte {
	cmd, err := json.Marshal(map[string]interface{}{
		"prefix": "df",
		"detail": "detail",
		"format": "json",
	})
	if err != nil {
		// panic! because ideally in no world this hard-coded input
		// should fail.
		panic(err)
	}
	return cmd
}

// Describe fulfills the prometheus.Collector's interface and sends the descriptors
// of pool's metrics to the given channel.
func (p *PoolUsageCollector) Describe(ch chan<- *prometheus.Desc) {
	for _, metric := range p.collectorList() {
		metric.Describe(ch)
	}
}

// Collect extracts the current values of all the metrics and sends them to the
// prometheus channel.
func (p *PoolUsageCollector) Collect(ch chan<- prometheus.Metric) {
	if err := p.collect(); err != nil {
		log.Println("[ERROR] failed collecting pool usage metrics:", err)
		return
	}

	for _, metric := range p.collectorList() {
		metric.Collect(ch)
	}
}
<commit_msg>pool: remove error log when no pools present<commit_after>//   Copyright 2016 DigitalOcean
//
//   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 collectors

import (
	"encoding/json"
	"log"

	"github.com/prometheus/client_golang/prometheus"
)

// PoolUsageCollector displays statistics about each pool we have created
// in the ceph cluster.
type PoolUsageCollector struct {
	conn Conn

	// UsedBytes tracks the amount of bytes currently allocated for the pool. This
	// does not factor in the overcommitment made for individual images.
	UsedBytes *prometheus.GaugeVec

	// RawUsedBytes tracks the amount of raw bytes currently used for the pool. This
	// factors in the replication factor (size) of the pool.
	RawUsedBytes *prometheus.GaugeVec

	// MaxAvail tracks the amount of bytes currently free for the pool,
	// which depends on the replication settings for the pool in question.
	MaxAvail *prometheus.GaugeVec

	// Objects shows the no. of RADOS objects created within the pool.
	Objects *prometheus.GaugeVec

	// DirtyObjects shows the no. of RADOS dirty objects in a cache-tier pool,
	// this doesn't make sense in a regular pool, see:
	// http://lists.ceph.com/pipermail/ceph-users-ceph.com/2015-April/000557.html
	DirtyObjects *prometheus.GaugeVec

	// ReadIO tracks the read IO calls made for the images within each pool.
	ReadIO *prometheus.GaugeVec

	// Readbytes tracks the read throughput made for the images within each pool.
	ReadBytes *prometheus.GaugeVec

	// WriteIO tracks the write IO calls made for the images within each pool.
	WriteIO *prometheus.GaugeVec

	// WriteBytes tracks the write throughput made for the images within each pool.
	WriteBytes *prometheus.GaugeVec
}

// NewPoolUsageCollector creates a new instance of PoolUsageCollector and returns
// its reference.
func NewPoolUsageCollector(conn Conn, cluster string) *PoolUsageCollector {
	var (
		subSystem = "pool"
		poolLabel = []string{"pool"}
	)

	labels := make(prometheus.Labels)
	labels["cluster"] = cluster

	return &PoolUsageCollector{
		conn: conn,

		UsedBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "used_bytes",
				Help:        "Capacity of the pool that is currently under use",
				ConstLabels: labels,
			},
			poolLabel,
		),
		RawUsedBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "raw_used_bytes",
				Help:        "Raw capacity of the pool that is currently under use, this factors in the size",
				ConstLabels: labels,
			},
			poolLabel,
		),
		MaxAvail: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "available_bytes",
				Help:        "Free space for this ceph pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		Objects: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "objects_total",
				Help:        "Total no. of objects allocated within the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		DirtyObjects: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "dirty_objects_total",
				Help:        "Total no. of dirty objects in a cache-tier pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		ReadIO: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "read_total",
				Help:        "Total read i/o calls for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		ReadBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "read_bytes_total",
				Help:        "Total read throughput for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		WriteIO: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "write_total",
				Help:        "Total write i/o calls for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
		WriteBytes: prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace:   cephNamespace,
				Subsystem:   subSystem,
				Name:        "write_bytes_total",
				Help:        "Total write throughput for the pool",
				ConstLabels: labels,
			},
			poolLabel,
		),
	}
}

func (p *PoolUsageCollector) collectorList() []prometheus.Collector {
	return []prometheus.Collector{
		p.UsedBytes,
		p.RawUsedBytes,
		p.MaxAvail,
		p.Objects,
		p.DirtyObjects,
		p.ReadIO,
		p.ReadBytes,
		p.WriteIO,
		p.WriteBytes,
	}
}

type cephPoolStats struct {
	Pools []struct {
		Name  string `json:"name"`
		ID    int    `json:"id"`
		Stats struct {
			BytesUsed    float64 `json:"bytes_used"`
			RawBytesUsed float64 `json:"raw_bytes_used"`
			MaxAvail     float64 `json:"max_avail"`
			Objects      float64 `json:"objects"`
			DirtyObjects float64 `json:"dirty"`
			ReadIO       float64 `json:"rd"`
			ReadBytes    float64 `json:"rd_bytes"`
			WriteIO      float64 `json:"wr"`
			WriteBytes   float64 `json:"wr_bytes"`
		} `json:"stats"`
	} `json:"pools"`
}

func (p *PoolUsageCollector) collect() error {
	cmd := p.cephUsageCommand()
	buf, _, err := p.conn.MonCommand(cmd)
	if err != nil {
		return err
	}

	stats := &cephPoolStats{}
	if err := json.Unmarshal(buf, stats); err != nil {
		return err
	}

	for _, pool := range stats.Pools {
		p.UsedBytes.WithLabelValues(pool.Name).Set(pool.Stats.BytesUsed)
		p.RawUsedBytes.WithLabelValues(pool.Name).Set(pool.Stats.RawBytesUsed)
		p.MaxAvail.WithLabelValues(pool.Name).Set(pool.Stats.MaxAvail)
		p.Objects.WithLabelValues(pool.Name).Set(pool.Stats.Objects)
		p.DirtyObjects.WithLabelValues(pool.Name).Set(pool.Stats.DirtyObjects)
		p.ReadIO.WithLabelValues(pool.Name).Set(pool.Stats.ReadIO)
		p.ReadBytes.WithLabelValues(pool.Name).Set(pool.Stats.ReadBytes)
		p.WriteIO.WithLabelValues(pool.Name).Set(pool.Stats.WriteIO)
		p.WriteBytes.WithLabelValues(pool.Name).Set(pool.Stats.WriteBytes)
	}

	return nil
}

func (p *PoolUsageCollector) cephUsageCommand() []byte {
	cmd, err := json.Marshal(map[string]interface{}{
		"prefix": "df",
		"detail": "detail",
		"format": "json",
	})
	if err != nil {
		// panic! because ideally in no world this hard-coded input
		// should fail.
		panic(err)
	}
	return cmd
}

// Describe fulfills the prometheus.Collector's interface and sends the descriptors
// of pool's metrics to the given channel.
func (p *PoolUsageCollector) Describe(ch chan<- *prometheus.Desc) {
	for _, metric := range p.collectorList() {
		metric.Describe(ch)
	}
}

// Collect extracts the current values of all the metrics and sends them to the
// prometheus channel.
func (p *PoolUsageCollector) Collect(ch chan<- prometheus.Metric) {
	if err := p.collect(); err != nil {
		log.Println("[ERROR] failed collecting pool usage metrics:", err)
		return
	}

	for _, metric := range p.collectorList() {
		metric.Collect(ch)
	}
}
<|endoftext|>


<commit_before>package git

import (
	"fmt"
	"path/filepath"
	"strings"
	"time"

	"github.com/ovh/cds/sdk"
)

// CloneOpts is a optional structs for git clone command
type CloneOpts struct {
	Depth                   int
	SingleBranch            bool
	Branch                  string
	Tag                     string
	Recursive               bool
	Verbose                 bool
	Quiet                   bool
	CheckoutCommit          string
	NoStrictHostKeyChecking bool
	ForceGetGitDescribe     bool
}

// Clone make a git clone
func Clone(repo, workdirPath, path string, auth *AuthOpts, opts *CloneOpts, output *OutputOpts) (string, error) {
	if verbose {
		t1 := time.Now()
		if opts != nil && opts.CheckoutCommit != "" {
			defer LogFunc("Checkout commit %s", opts.CheckoutCommit)
		}
		defer func(start time.Time) {
			LogFunc("Git clone %s (%v s)", path, int(time.Since(start).Seconds()))
		}(t1)
	}

	var commands []cmd
	repoURL, err := getRepoURL(repo, auth)
	if err != nil {
		return "", err
	}

	var userLogCommand string
	userLogCommand, commands, err = prepareGitCloneCommands(repoURL, workdirPath, path, opts)
	if err != nil {
		return "", err
	}
	return userLogCommand, runGitCommands(repo, commands, auth, output)
}

func prepareGitCloneCommands(repo, workdirPath, path string, opts *CloneOpts) (string, cmds, error) {
	allCmd := []cmd{}
	var err error
	workdirPath, err = filepath.Abs(workdirPath)
	if err != nil {
		return "", nil, sdk.WithStack(err)
	}
	gitcmd := cmd{
		cmd:     "git",
		workdir: workdirPath,
		args:    []string{"clone"},
	}

	if opts != nil {
		if opts.Quiet {
			gitcmd.args = append(gitcmd.args, "--quiet")
		} else if opts.Verbose {
			gitcmd.args = append(gitcmd.args, "--verbose")
		}

		if opts.Depth != 0 {
			gitcmd.args = append(gitcmd.args, "--depth", fmt.Sprintf("%d", opts.Depth))
		}

		if opts.Branch != "" || (opts.Tag != "" && opts.Tag != sdk.DefaultGitCloneParameterTagValue) {
			if opts.Tag != "" && opts.Tag != sdk.DefaultGitCloneParameterTagValue {
				gitcmd.args = append(gitcmd.args, "--branch", opts.Tag)
			} else {
				gitcmd.args = append(gitcmd.args, "--branch", opts.Branch)
			}
		} else if opts.SingleBranch {
			gitcmd.args = append(gitcmd.args, "--single-branch")
		}

		if opts.Recursive {
			gitcmd.args = append(gitcmd.args, "--recursive")
		}
	}

	userLogCommand := "Executing: git " + strings.Join(gitcmd.args, " ") + "...  "
	gitcmd.args = append(gitcmd.args, repo)

	if path != "" {
		gitcmd.args = append(gitcmd.args, path)
	}

	allCmd = append(allCmd, gitcmd)

	// if a specific commit hash is given, try to reset current repo to this commit
	// when a tag is given the commit hash is ignored
	if opts != nil && opts.CheckoutCommit != "" && opts.Tag == "" {
		// if no branch was given, this means that we cloned the repo on the default branch, we need to fetch the target commit hash
		// fetching a specific commit hash will not work for old git version (1.7 for example)
		if opts.Branch == "" {
			fetchCmd := cmd{
				cmd:  "git",
				args: []string{"fetch", "origin", opts.CheckoutCommit},
			}
			userLogCommand += "\n\rExecuting: git " + strings.Join(fetchCmd.args, " ")
			//Locate the git reset cmd to the right directory
			if path == "" {
				t := strings.Split(repo, "/")
				fetchCmd.workdir = filepath.Join(workdirPath, strings.TrimSuffix(t[len(t)-1], ".git"))
			} else {
				fetchCmd.workdir = filepath.Join(workdirPath, path)
			}

			allCmd = append(allCmd, fetchCmd)
		}

		// even if we cloned the right branch, we need to reset to the given commit hash that could be different than HEAD
		resetCmd := cmd{
			cmd:  "git",
			args: []string{"reset", "--hard", opts.CheckoutCommit},
		}
		userLogCommand += "\n\rExecuting: git " + strings.Join(resetCmd.args, " ")
		// locate the git reset cmd to the right directory
		if path == "" {
			t := strings.Split(repo, "/")
			resetCmd.workdir = filepath.Join(workdirPath, strings.TrimSuffix(t[len(t)-1], ".git"))
		} else {
			resetCmd.workdir = filepath.Join(workdirPath, path)
		}

		allCmd = append(allCmd, resetCmd)
	}

	return userLogCommand, cmds(allCmd), nil
}
<commit_msg>fix(worker): do not concat absolute path that starts<commit_after>package git

import (
	"fmt"
	"path/filepath"
	"strings"
	"time"

	"github.com/ovh/cds/sdk"
)

// CloneOpts is a optional structs for git clone command
type CloneOpts struct {
	Depth                   int
	SingleBranch            bool
	Branch                  string
	Tag                     string
	Recursive               bool
	Verbose                 bool
	Quiet                   bool
	CheckoutCommit          string
	NoStrictHostKeyChecking bool
	ForceGetGitDescribe     bool
}

// Clone make a git clone
func Clone(repo, workdirPath, path string, auth *AuthOpts, opts *CloneOpts, output *OutputOpts) (string, error) {
	if verbose {
		t1 := time.Now()
		if opts != nil && opts.CheckoutCommit != "" {
			defer LogFunc("Checkout commit %s", opts.CheckoutCommit)
		}
		defer func(start time.Time) {
			LogFunc("Git clone %s (%v s)", path, int(time.Since(start).Seconds()))
		}(t1)
	}

	var commands []cmd
	repoURL, err := getRepoURL(repo, auth)
	if err != nil {
		return "", err
	}

	var userLogCommand string
	userLogCommand, commands, err = prepareGitCloneCommands(repoURL, workdirPath, path, opts)
	if err != nil {
		return "", err
	}
	return userLogCommand, runGitCommands(repo, commands, auth, output)
}

func prepareGitCloneCommands(repo, workdirPath, path string, opts *CloneOpts) (string, cmds, error) {
	allCmd := []cmd{}
	var err error
	workdirPath, err = filepath.Abs(workdirPath)
	if err != nil {
		return "", nil, sdk.WithStack(err)
	}
	gitcmd := cmd{
		cmd:     "git",
		workdir: workdirPath,
		args:    []string{"clone"},
	}

	if opts != nil {
		if opts.Quiet {
			gitcmd.args = append(gitcmd.args, "--quiet")
		} else if opts.Verbose {
			gitcmd.args = append(gitcmd.args, "--verbose")
		}

		if opts.Depth != 0 {
			gitcmd.args = append(gitcmd.args, "--depth", fmt.Sprintf("%d", opts.Depth))
		}

		if opts.Branch != "" || (opts.Tag != "" && opts.Tag != sdk.DefaultGitCloneParameterTagValue) {
			if opts.Tag != "" && opts.Tag != sdk.DefaultGitCloneParameterTagValue {
				gitcmd.args = append(gitcmd.args, "--branch", opts.Tag)
			} else {
				gitcmd.args = append(gitcmd.args, "--branch", opts.Branch)
			}
		} else if opts.SingleBranch {
			gitcmd.args = append(gitcmd.args, "--single-branch")
		}

		if opts.Recursive {
			gitcmd.args = append(gitcmd.args, "--recursive")
		}
	}

	userLogCommand := "Executing: git " + strings.Join(gitcmd.args, " ") + "...  "
	gitcmd.args = append(gitcmd.args, repo)

	if path != "" {
		gitcmd.args = append(gitcmd.args, path)
	}

	allCmd = append(allCmd, gitcmd)

	// if a specific commit hash is given, try to reset current repo to this commit
	// when a tag is given the commit hash is ignored
	if opts != nil && opts.CheckoutCommit != "" && opts.Tag == "" {
		// if no branch was given, this means that we cloned the repo on the default branch, we need to fetch the target commit hash
		// fetching a specific commit hash will not work for old git version (1.7 for example)
		if opts.Branch == "" {
			fetchCmd := cmd{
				cmd:  "git",
				args: []string{"fetch", "origin", opts.CheckoutCommit},
			}
			userLogCommand += "\n\rExecuting: git " + strings.Join(fetchCmd.args, " ")
			//Locate the git reset cmd to the right directory
			if path == "" {
				t := strings.Split(repo, "/")
				fetchCmd.workdir = filepath.Join(workdirPath, strings.TrimSuffix(t[len(t)-1], ".git"))
			} else if strings.HasPrefix(path, "/") {
				fetchCmd.workdir = path
			} else {
				fetchCmd.workdir = filepath.Join(workdirPath, path)
			}

			allCmd = append(allCmd, fetchCmd)
		}

		// even if we cloned the right branch, we need to reset to the given commit hash that could be different than HEAD
		resetCmd := cmd{
			cmd:  "git",
			args: []string{"reset", "--hard", opts.CheckoutCommit},
		}
		userLogCommand += "\n\rExecuting: git " + strings.Join(resetCmd.args, " ")
		// locate the git reset cmd to the right directory
		if path == "" {
			t := strings.Split(repo, "/")
			resetCmd.workdir = filepath.Join(workdirPath, strings.TrimSuffix(t[len(t)-1], ".git"))
		} else {
			resetCmd.workdir = filepath.Join(workdirPath, path)
		}

		allCmd = append(allCmd, resetCmd)
	}

	return userLogCommand, cmds(allCmd), nil
}
<|endoftext|>


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

package main

import (
	"exec"
	"flag"
	"http"
	"io"
	"io/ioutil"
	"log"
	"os"
	"runtime"
	"strconv"
	"template"
)

var (
	httpListen = flag.String("http", "127.0.0.1:3999", "host:port to listen on")
	htmlOutput = flag.Bool("html", false, "render program output as HTML")
)

var (
	// a source of numbers, for naming temporary files
	uniq = make(chan int)
	// the architecture-identifying character of the tool chain, 5, 6, or 8
	archChar string
)

func main() {
	flag.Parse()

	// set archChar
	switch runtime.GOARCH {
	case "arm":
		archChar = "5"
	case "amd64":
		archChar = "6"
	case "386":
		archChar = "8"
	default:
		log.Fatalln("unrecognized GOARCH:", runtime.GOARCH)
	}

	// source of unique numbers
	go func() {
		for i := 0; ; i++ {
			uniq <- i
		}
	}()

	http.HandleFunc("/", FrontPage)
	http.HandleFunc("/compile", Compile)
	log.Fatal(http.ListenAndServe(*httpListen, nil))
}

// FrontPage is an HTTP handler that renders the goplay interface.
// If a filename is supplied in the path component of the URI,
// its contents will be put in the interface's text area.
// Otherwise, the default "hello, world" program is displayed.
func FrontPage(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadFile(req.URL.Path[1:])
	if err != nil {
		data = helloWorld
	}
	frontPage.Execute(w, data)
}

// Compile is an HTTP handler that reads Go source code from the request,
// compiles and links the code (returning any errors), runs the program,
// and sends the program's output as the HTTP response.
func Compile(w http.ResponseWriter, req *http.Request) {
	// x is the base name for .go, .6, executable files
	x := os.TempDir() + "/compile" + strconv.Itoa(<-uniq)
	src := x + ".go"
	obj := x + "." + archChar
	bin := x
	if runtime.GOOS == "windows" {
		bin += ".exe"
	}

	// write request Body to x.go
	f, err := os.Create(src)
	if err != nil {
		error(w, nil, err)
		return
	}
	defer os.Remove(src)
	defer f.Close()
	_, err = io.Copy(f, req.Body)
	if err != nil {
		error(w, nil, err)
		return
	}
	f.Close()

	// build x.go, creating x.6
	out, err := run(archChar+"g", "-o", obj, src)
	defer os.Remove(obj)
	if err != nil {
		error(w, out, err)
		return
	}

	// link x.6, creating x (the program binary)
	out, err = run(archChar+"l", "-o", bin, obj)
	defer os.Remove(bin)
	if err != nil {
		error(w, out, err)
		return
	}

	// run x
	out, err = run(bin)
	if err != nil {
		error(w, out, err)
	}

	// write the output of x as the http response
	if *htmlOutput {
		w.Write(out)
	} else {
		output.Execute(w, out)
	}
}

// error writes compile, link, or runtime errors to the HTTP connection.
// The JavaScript interface uses the 404 status code to identify the error.
func error(w http.ResponseWriter, out []byte, err os.Error) {
	w.WriteHeader(404)
	if out != nil {
		output.Execute(w, out)
	} else {
		output.Execute(w, err.String())
	}
}

// run executes the specified command and returns its output and an error.
func run(cmd ...string) ([]byte, os.Error) {
	return exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
}

var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template
var output = template.Must(template.New("output").Parse(outputText))          // HTML template

var outputText = `<pre>{{html .}}</pre>`

var frontPageText = `<!doctype html>

<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{printf "%s" . |html}}</textarea>

(Shift-Enter to compile and run.)
<input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke

`

var helloWorld = []byte(`package main

import "fmt"

func main() {
	fmt.Println("hello, world")
}
`)
<commit_msg>misc/goplay: another template fix<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"exec"
	"flag"
	"http"
	"io"
	"io/ioutil"
	"log"
	"os"
	"runtime"
	"strconv"
	"template"
)

var (
	httpListen = flag.String("http", "127.0.0.1:3999", "host:port to listen on")
	htmlOutput = flag.Bool("html", false, "render program output as HTML")
)

var (
	// a source of numbers, for naming temporary files
	uniq = make(chan int)
	// the architecture-identifying character of the tool chain, 5, 6, or 8
	archChar string
)

func main() {
	flag.Parse()

	// set archChar
	switch runtime.GOARCH {
	case "arm":
		archChar = "5"
	case "amd64":
		archChar = "6"
	case "386":
		archChar = "8"
	default:
		log.Fatalln("unrecognized GOARCH:", runtime.GOARCH)
	}

	// source of unique numbers
	go func() {
		for i := 0; ; i++ {
			uniq <- i
		}
	}()

	http.HandleFunc("/", FrontPage)
	http.HandleFunc("/compile", Compile)
	log.Fatal(http.ListenAndServe(*httpListen, nil))
}

// FrontPage is an HTTP handler that renders the goplay interface.
// If a filename is supplied in the path component of the URI,
// its contents will be put in the interface's text area.
// Otherwise, the default "hello, world" program is displayed.
func FrontPage(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadFile(req.URL.Path[1:])
	if err != nil {
		data = helloWorld
	}
	frontPage.Execute(w, data)
}

// Compile is an HTTP handler that reads Go source code from the request,
// compiles and links the code (returning any errors), runs the program,
// and sends the program's output as the HTTP response.
func Compile(w http.ResponseWriter, req *http.Request) {
	// x is the base name for .go, .6, executable files
	x := os.TempDir() + "/compile" + strconv.Itoa(<-uniq)
	src := x + ".go"
	obj := x + "." + archChar
	bin := x
	if runtime.GOOS == "windows" {
		bin += ".exe"
	}

	// write request Body to x.go
	f, err := os.Create(src)
	if err != nil {
		error(w, nil, err)
		return
	}
	defer os.Remove(src)
	defer f.Close()
	_, err = io.Copy(f, req.Body)
	if err != nil {
		error(w, nil, err)
		return
	}
	f.Close()

	// build x.go, creating x.6
	out, err := run(archChar+"g", "-o", obj, src)
	defer os.Remove(obj)
	if err != nil {
		error(w, out, err)
		return
	}

	// link x.6, creating x (the program binary)
	out, err = run(archChar+"l", "-o", bin, obj)
	defer os.Remove(bin)
	if err != nil {
		error(w, out, err)
		return
	}

	// run x
	out, err = run(bin)
	if err != nil {
		error(w, out, err)
	}

	// write the output of x as the http response
	if *htmlOutput {
		w.Write(out)
	} else {
		output.Execute(w, out)
	}
}

// error writes compile, link, or runtime errors to the HTTP connection.
// The JavaScript interface uses the 404 status code to identify the error.
func error(w http.ResponseWriter, out []byte, err os.Error) {
	w.WriteHeader(404)
	if out != nil {
		output.Execute(w, out)
	} else {
		output.Execute(w, err.String())
	}
}

// run executes the specified command and returns its output and an error.
func run(cmd ...string) ([]byte, os.Error) {
	return exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
}

var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template
var output = template.Must(template.New("output").Parse(outputText))          // HTML template

var outputText = `<pre>{{printf "%s" . |html}}</pre>`

var frontPageText = `<!doctype html>

<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{printf "%s" . |html}}</textarea>

(Shift-Enter to compile and run.)
<input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke

`

var helloWorld = []byte(`package main

import "fmt"

func main() {
	fmt.Println("hello, world")
}
`)
<|endoftext|>


<commit_before>package commands

import (
	"bufio"
	"bytes"
	"github.com/stretchr/testify/assert"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
	"strings"
	"time"
)

var currentDir, _ = os.Getwd()

func randomTempFile(t *testing.T) string {
	file, err := ioutil.TempFile("", "archive_")
	assert.NoError(t, err)
	defer file.Close()
	defer os.Remove(file.Name())
	return file.Name()
}

func createArchiveCommand(t *testing.T) *ArchiveCommand {
	err := os.Chdir(filepath.Join(currentDir, ".."))
	assert.NoError(t, err)

	return &ArchiveCommand{
		Output: randomTempFile(t),
		Silent: true,
	}
}

func filesInFolder(path string) []string {
	matches, _ := filepath.Glob(path)
	return matches
}

func readArchiveContent(t *testing.T, c *ArchiveCommand) (resultMap map[string]bool) {
	resultMap = make(map[string]bool)

	cmd := exec.Command("tar", "-ztf", c.Output)
	cmd.Env = os.Environ()
	cmd.Stderr = os.Stderr
	result, err := cmd.Output()
	assert.NoError(t, err)

	reader := bufio.NewReader(bytes.NewReader(result))
	for {
		line, prefix, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		assert.NoError(t, err, "ReadLine")
		assert.False(t, prefix, "ReadLine")
		file := strings.TrimSpace(string(line))
		resultMap[file] = true
	}

	return
}

func verifyArchiveContent(t *testing.T, c *ArchiveCommand, files ...string) {
	resultMap := readArchiveContent(t, c)
	for _, file := range files {
		assert.True(t, resultMap[file], "File should exist %q", file)
		delete(resultMap, file)
	}
	assert.Len(t, resultMap, 0, "No extra file should exist")
}

func TestArchiveNotCreatingArchive(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Execute(nil)
	_, err := os.Stat(cmd.Output)
	assert.True(t, os.IsNotExist(err), "File should not exist", cmd.Output, err)
}

func TestArchiveAddingSomeLocalFiles(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Paths = []string{
		"commands/*",
	}
	cmd.Execute(nil)
	verifyArchiveContent(t, cmd, filesInFolder("commands/*")...)
}

func TestArchiveNotAddingDuplicateFiles(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Paths = []string{
		"commands/*",
		"commands/archive.go",
	}
	cmd.Execute(nil)
	verifyArchiveContent(t, cmd, filesInFolder("commands/*")...)
}

func TestArchiveAddingUntrackedFiles(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Untracked = true
	cmd.Execute(nil)
	files := readArchiveContent(t, cmd)
	assert.NotEmpty(t, files)
}

func TestArchiveUpdating(t *testing.T) {
	tempFile := randomTempFile(t)
	defer os.Remove(tempFile)

	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Paths = []string{
		"commands",
		tempFile,
	}

	cmd.Execute(nil)
	archive1, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")

	cmd.Execute(nil)
	archive2, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")
	assert.Equal(t, archive1.ModTime(), archive2.ModTime(), "Archive should not be modyfied")

	time.Sleep(time.Second)
	err = ioutil.WriteFile(tempFile, []byte{}, 0700)
	assert.NoError(t, err, "File is created")

	cmd.Execute(nil)
	archive3, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")
	assert.NotEqual(t, archive2.ModTime(), archive3.ModTime(), "File is added to archive")

	time.Sleep(time.Second)
	err = ioutil.WriteFile(tempFile, []byte{}, 0700)
	assert.NoError(t, err, "File is updated")

	cmd.Execute(nil)
	archive4, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")
	assert.NotEqual(t, archive3.ModTime(), archive4.ModTime(), "File is updated in archive")
}

<commit_msg>Fix untracked file tests<commit_after>package commands

import (
	"bufio"
	"bytes"
	"github.com/stretchr/testify/assert"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
	"strings"
	"time"
)

const UntrackedFileName = "some_fancy_untracked_file"

var currentDir, _ = os.Getwd()

func randomTempFile(t *testing.T) string {
	file, err := ioutil.TempFile("", "archive_")
	assert.NoError(t, err)
	defer file.Close()
	defer os.Remove(file.Name())
	return file.Name()
}

func createArchiveCommand(t *testing.T) *ArchiveCommand {
	err := os.Chdir(filepath.Join(currentDir, ".."))
	assert.NoError(t, err)

	return &ArchiveCommand{
		Output: randomTempFile(t),
		Silent: true,
	}
}

func filesInFolder(path string) []string {
	matches, _ := filepath.Glob(path)
	return matches
}

func readArchiveContent(t *testing.T, c *ArchiveCommand) (resultMap map[string]bool) {
	resultMap = make(map[string]bool)

	cmd := exec.Command("tar", "-ztf", c.Output)
	cmd.Env = os.Environ()
	cmd.Stderr = os.Stderr
	result, err := cmd.Output()
	assert.NoError(t, err)

	reader := bufio.NewReader(bytes.NewReader(result))
	for {
		line, prefix, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		assert.NoError(t, err, "ReadLine")
		assert.False(t, prefix, "ReadLine")
		file := strings.TrimSpace(string(line))
		resultMap[file] = true
	}

	return
}

func verifyArchiveContent(t *testing.T, c *ArchiveCommand, files ...string) {
	resultMap := readArchiveContent(t, c)
	for _, file := range files {
		assert.True(t, resultMap[file], "File should exist %q", file)
		delete(resultMap, file)
	}
	assert.Len(t, resultMap, 0, "No extra file should exist")
}

func TestArchiveNotCreatingArchive(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Execute(nil)
	_, err := os.Stat(cmd.Output)
	assert.True(t, os.IsNotExist(err), "File should not exist", cmd.Output, err)
}

func TestArchiveAddingSomeLocalFiles(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Paths = []string{
		"commands/*",
	}
	cmd.Execute(nil)
	verifyArchiveContent(t, cmd, filesInFolder("commands/*")...)
}

func TestArchiveNotAddingDuplicateFiles(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Paths = []string{
		"commands/*",
		"commands/archive.go",
	}
	cmd.Execute(nil)
	verifyArchiveContent(t, cmd, filesInFolder("commands/*")...)
}

func TestArchiveAddingUntrackedFiles(t *testing.T) {
	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	err := ioutil.WriteFile(UntrackedFileName, []byte{}, 0700)
	assert.NoError(t, err)
	cmd.Untracked = true
	cmd.Execute(nil)
	files := readArchiveContent(t, cmd)
	assert.NotEmpty(t, files)
	assert.True(t, files[UntrackedFileName])
}

func TestArchiveUpdating(t *testing.T) {
	tempFile := randomTempFile(t)
	defer os.Remove(tempFile)

	cmd := createArchiveCommand(t)
	defer os.Remove(cmd.Output)
	cmd.Paths = []string{
		"commands",
		tempFile,
	}

	cmd.Execute(nil)
	archive1, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")

	cmd.Execute(nil)
	archive2, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")
	assert.Equal(t, archive1.ModTime(), archive2.ModTime(), "Archive should not be modyfied")

	time.Sleep(time.Second)
	err = ioutil.WriteFile(tempFile, []byte{}, 0700)
	assert.NoError(t, err, "File is created")

	cmd.Execute(nil)
	archive3, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")
	assert.NotEqual(t, archive2.ModTime(), archive3.ModTime(), "File is added to archive")

	time.Sleep(time.Second)
	err = ioutil.WriteFile(tempFile, []byte{}, 0700)
	assert.NoError(t, err, "File is updated")

	cmd.Execute(nil)
	archive4, err := os.Stat(cmd.Output)
	assert.NoError(t, err, "Archive is created")
	assert.NotEqual(t, archive3.ModTime(), archive4.ModTime(), "File is updated in archive")
}

<|endoftext|>


<commit_before>package graval

type FTPDriverFactory interface {
	NewDriver() FTPDriver
}

type FTPDriver interface {
	Authenticate(string, string) bool
}
<commit_msg>expand the FTPDriver interface<commit_after>package graval

import (
	"time"
)

type FTPDriverFactory interface {
	NewDriver() FTPDriver
}

type FTPDriver interface {
    // params  - username, password
	// returns - true if the provided details are valid
	Authenticate(string, string) bool

    // params  - a file path
	// returns - an int with the number of bytes in the file or -1 if the file
    //           doesn't exist
	Bytes(string) int

    // params  - a file path
	// returns - a time indicating when the requested path was last modified
	ModifiedTime(string) time.Time

    // params  - path
	// returns - true if the current user is permitted to change to the
	//           requested path
	ChangeDir(string) bool

    // params  - path
	// returns - a collection of items describing the contents of the requested
	//           path
	DirContents(string) bool

    // params  - path
	// returns - true if the directory was deleted
	DeleteDir(string) bool

    // params  - path
	// returns - true if the file was deleted
	DeleteFile(string) bool

    // params  - from_path, to_path
	// returns - true if the file was renamed
	Rename(string, string) bool

    // params  - path
	// returns - true if the new directory was created
	MakeDir(string) bool

    // params  - path
	// returns - the file to send back to the current user
	GetFile(string) int

    // params  - desination path, temp file path
	// returns - the number of bytes saved to the desination path or -1 if
	//           there was an issue
	PutFile(string, string) int
}
<|endoftext|>


<commit_before>package blockindex

import (
	"math/big"
	"sort"
	"fmt"

	"github.com/btcboost/copernicus/model/block"
	"github.com/btcboost/copernicus/util"
)

/**
 * The block chain is a tree shaped structure starting with the genesis block at
 * the root, with each block potentially having multiple candidates to be the
 * next block. A blockIndex may have multiple prev pointing to it, but at most
 * one of them can be part of the currently active branch.
 */

 const (
 	StatusAllValid uint32 = 1 << iota
 	StatusIndexStored
 	StatusDataStored
	StatusWaitingData
	StatusFailed
	StatusAccepted

	//NOTE: This must be defined last in order to avoid influencing iota
	StatusNone  = 0
 )

type BlockIndex struct {
	Header block.BlockHeader
	// pointer to the hash of the block, if any.
	blockHash util.Hash
	// pointer to the index of the predecessor of this block
	Prev *BlockIndex
	// pointer to the index of some further predecessor of this block
	Skip *BlockIndex
	// height of the entry in the chain. The genesis block has height 0；
	Height int32
	// Which # file this block is stored in (blk?????.dat)
	File int
	// Byte offset within blk?????.dat where this block's data is stored
	DataPos int
	// Byte offset within rev?????.dat where this block's undo data is stored
	UndoPos int
	// (memory only) Total amount of work (expected number of hashes) in the
	// chain up to and including this block
	ChainWork big.Int
	// Number of transactions in this block.
	// Note: in a potential headers-first mode, this number cannot be relied
	// upon
	TxCount int
	// (memory only) Number of transactions in the chain up to and including
	// this block.
	// This value will be non-zero only if and only if transactions for this
	// block and all its parents are available. Change to 64-bit type when
	// necessary; won't happen before 2030
	ChainTxCount int
	//status of this block. See enum
	Status uint32
	// (memory only) Sequential id assigned to distinguish order in which
	// blocks are received.
	SequenceID int32
	// (memory only) Maximum time in the chain upto and including this block.
	TimeMax uint32
}

const medianTimeSpan = 11

func (bIndex *BlockIndex) SetNull() {
	bIndex.Header.SetNull()
	bIndex.blockHash = util.Hash{}
	bIndex.Prev = nil
	bIndex.Skip = nil

	bIndex.Height = 0
	bIndex.File = -1
	bIndex.DataPos = -1
	bIndex.UndoPos = -1
	bIndex.ChainWork = big.Int{}
	bIndex.ChainTxCount = 0
	bIndex.TxCount = 0
	bIndex.Status = StatusNone
	bIndex.SequenceID = 0
	bIndex.TimeMax = 0
}

func (bIndex *BlockIndex) WaitingData() bool {
	return bIndex.Status & StatusWaitingData == 0
}

func (bIndex *BlockIndex) AllValid() bool {
	return bIndex.Status & StatusAllValid != 0
}

func (bIndex *BlockIndex) IndexStored() bool {
	return bIndex.Status & StatusIndexStored != 0
}

func (bIndex *BlockIndex) AllStored() bool {
	return bIndex.Status & StatusDataStored != 0
}

func (bIndex *BlockIndex) Accepted() bool {
	return bIndex.Status & StatusAccepted != 0
}

func (bIndex *BlockIndex) Failed() bool {
	return bIndex.Status & StatusFailed != 0
}

func (bIndex *BlockIndex) AddStatus(statu uint32) {
	bIndex.Status |= statu
}

func (bIndex *BlockIndex) SubStatus(statu uint32) {
	bIndex.Status &= ^statu
}

func (bIndex *BlockIndex) GetDataPos() int {

	return 0
}

func (bIndex *BlockIndex) GetUndoPos() block.DiskBlockPos {
	return block.DiskBlockPos{File:bIndex.File,Pos:bIndex.UndoPos}
}

func (bIndex *BlockIndex) GetBlockPos() block.DiskBlockPos {
	return block.DiskBlockPos{File:bIndex.File,Pos:bIndex.DataPos}
}

func (bIndex *BlockIndex) GetBlockHeader() *block.BlockHeader {

	return &bIndex.Header
}

func (bIndex *BlockIndex) GetBlockHash() *util.Hash {
	if bIndex.blockHash.IsNull(){
		bIndex.blockHash = bIndex.Header.GetHash()
	}
	if bIndex.blockHash.IsEqual(&util.Hash{}) {
		bIndex.blockHash = bIndex.Header.GetHash()
	}
	return &bIndex.blockHash
}

func (bIndex *BlockIndex) SetBlockHash(hash util.Hash) {
	bIndex.blockHash =  hash
}

func (bIndex *BlockIndex) GetBlockTime() uint32 {

	return bIndex.Header.Time
}

func (bIndex *BlockIndex) GetBlockTimeMax() uint32 {
	return bIndex.TimeMax
}

func (bIndex *BlockIndex) GetMedianTimePast() int64 {
	median := make([]int64, 0, medianTimeSpan)
	index := bIndex
	numNodes := 0
	for i := 0; i < medianTimeSpan && index != nil; i++ {
		median = append(median, int64(index.GetBlockTime()))
		index = index.Prev
		numNodes++
	}
	median = median[:numNodes]
	sort.Slice(median, func(i, j int) bool {
		return median[i] < median[j]
	})

	return median[numNodes/2]
}

// IsValid checks whether this block index entry is valid up to the passed validity
// level.
func (bIndex *BlockIndex) IsValid(upto uint32) bool {

	return false
}

// RaiseValidity Raise the validity level of this block index entry.
// Returns true if the validity was changed.
func (bIndex *BlockIndex) RaiseValidity(upto uint32) bool {

	return false
}

func (bIndex *BlockIndex) BuildSkip() {
	if bIndex.Prev != nil {
		bIndex.Skip = bIndex.Prev.GetAncestor(getSkipHeight(bIndex.Height))
	}
}

// Turn the lowest '1' bit in the binary representation of a number into a '0'.
func invertLowestOne(n int32) int32 {
	return n & (n - 1)
}

// getSkipHeight Compute what height to jump back to with the CBlockIndex::pskip pointer.
func getSkipHeight(height int32) int32 {
	if height < 2 {
		return 0
	}

	// Determine which height to jump back to. Any number strictly lower than
	// height is acceptable, but the following expression seems to perform well
	// in simulations (max 110 steps to go back up to 2**18 blocks).
	if (height & 1) > 0 {
		return invertLowestOne(invertLowestOne(height-1)) + 1
	}
	return invertLowestOne(height)
}

// GetAncestor efficiently find an ancestor of this block.
func (bIndex *BlockIndex) GetAncestor(height int32) *BlockIndex {
	if height > bIndex.Height || height < 0 {
		return nil
	}
	indexWalk := bIndex
	heightWalk := bIndex.Height
	for heightWalk > height {
		heightSkip := getSkipHeight(heightWalk)
		heightSkipPrev := getSkipHeight(heightWalk - 1)
		if indexWalk.Skip != nil && (heightSkip == height ||
			(heightSkip > height && !(heightSkipPrev < heightSkip-2 && heightSkipPrev >= height))) {
			// Only follow skip if prev->skip isn't better than skip->prev.
			indexWalk = indexWalk.Skip
			heightWalk = heightSkip
		} else {
			if indexWalk.Prev == nil {
				panic("The blockIndex pointer should not be nil")
			}
			indexWalk = indexWalk.Prev
			heightWalk--
		}
	}

	return indexWalk
}

func (bIndex *BlockIndex) String() string {
	hash := bIndex.GetBlockHash()
	return fmt.Sprintf("BlockIndex(pprev=%p, height=%d, merkle=%s, hashBlock=%s)\n", bIndex.Prev,
		bIndex.Height, bIndex.Header.MerkleRoot.String(), hash.String())
}

func NewBlockIndex(blkHeader *block.BlockHeader) *BlockIndex {
	blockIndex := new(BlockIndex)
	blockIndex.SetNull()
	blockIndex.Header = *blkHeader

	return blockIndex
}

<commit_msg>fix bug<commit_after>package blockindex

import (
	"math/big"
	"sort"
	"fmt"

	"github.com/btcboost/copernicus/model/block"
	"github.com/btcboost/copernicus/util"
)

/**
 * The block chain is a tree shaped structure starting with the genesis block at
 * the root, with each block potentially having multiple candidates to be the
 * next block. A blockIndex may have multiple prev pointing to it, but at most
 * one of them can be part of the currently active branch.
 */

 const (
 	StatusAllValid uint32 = 1 << iota
 	StatusIndexStored
 	StatusDataStored
	StatusWaitingData
	StatusFailed
	StatusAccepted

	//NOTE: This must be defined last in order to avoid influencing iota
	StatusNone  = 0
 )

type BlockIndex struct {
	Header block.BlockHeader
	// pointer to the hash of the block, if any.
	blockHash util.Hash
	// pointer to the index of the predecessor of this block
	Prev *BlockIndex
	// pointer to the index of some further predecessor of this block
	Skip *BlockIndex
	// height of the entry in the chain. The genesis block has height 0；
	Height int32
	// Which # file this block is stored in (blk?????.dat)
	File int
	// Byte offset within blk?????.dat where this block's data is stored
	DataPos uint32
	// Byte offset within rev?????.dat where this block's undo data is stored
	UndoPos uint32
	// (memory only) Total amount of work (expected number of hashes) in the
	// chain up to and including this block
	ChainWork big.Int
	// Number of transactions in this block.
	// Note: in a potential headers-first mode, this number cannot be relied
	// upon
	TxCount int
	// (memory only) Number of transactions in the chain up to and including
	// this block.
	// This value will be non-zero only if and only if transactions for this
	// block and all its parents are available. Change to 64-bit type when
	// necessary; won't happen before 2030
	ChainTxCount int
	//status of this block. See enum
	Status uint32
	// (memory only) Sequential id assigned to distinguish order in which
	// blocks are received.
	SequenceID int32
	// (memory only) Maximum time in the chain upto and including this block.
	TimeMax uint32
}

const medianTimeSpan = 11

func (bIndex *BlockIndex) SetNull() {
	bIndex.Header.SetNull()
	bIndex.blockHash = util.Hash{}
	bIndex.Prev = nil
	bIndex.Skip = nil

	bIndex.Height = 0
	bIndex.File = -1
	bIndex.DataPos = 0
	bIndex.UndoPos = 0
	bIndex.ChainWork = big.Int{}
	bIndex.ChainTxCount = 0
	bIndex.TxCount = 0
	bIndex.Status = StatusNone
	bIndex.SequenceID = 0
	bIndex.TimeMax = 0
}

func (bIndex *BlockIndex) WaitingData() bool {
	return bIndex.Status & StatusWaitingData == 0
}

func (bIndex *BlockIndex) AllValid() bool {
	return bIndex.Status & StatusAllValid != 0
}

func (bIndex *BlockIndex) IndexStored() bool {
	return bIndex.Status & StatusIndexStored != 0
}

func (bIndex *BlockIndex) AllStored() bool {
	return bIndex.Status & StatusDataStored != 0
}

func (bIndex *BlockIndex) Accepted() bool {
	return bIndex.Status & StatusAccepted != 0
}

func (bIndex *BlockIndex) Failed() bool {
	return bIndex.Status & StatusFailed != 0
}

func (bIndex *BlockIndex) AddStatus(statu uint32) {
	bIndex.Status |= statu
}

func (bIndex *BlockIndex) SubStatus(statu uint32) {
	bIndex.Status &= ^statu
}

func (bIndex *BlockIndex) GetDataPos() int {

	return 0
}

func (bIndex *BlockIndex) GetUndoPos() block.DiskBlockPos {
	return block.DiskBlockPos{File:bIndex.File,Pos:bIndex.UndoPos}
}

func (bIndex *BlockIndex) GetBlockPos() block.DiskBlockPos {
	return block.DiskBlockPos{File:bIndex.File,Pos:bIndex.DataPos}
}

func (bIndex *BlockIndex) GetBlockHeader() *block.BlockHeader {

	return &bIndex.Header
}

func (bIndex *BlockIndex) GetBlockHash() *util.Hash {
	if bIndex.blockHash.IsNull(){
		bIndex.blockHash = bIndex.Header.GetHash()
	}
	if bIndex.blockHash.IsEqual(&util.Hash{}) {
		bIndex.blockHash = bIndex.Header.GetHash()
	}
	return &bIndex.blockHash
}

func (bIndex *BlockIndex) SetBlockHash(hash util.Hash) {
	bIndex.blockHash =  hash
}

func (bIndex *BlockIndex) GetBlockTime() uint32 {

	return bIndex.Header.Time
}

func (bIndex *BlockIndex) GetBlockTimeMax() uint32 {
	return bIndex.TimeMax
}

func (bIndex *BlockIndex) GetMedianTimePast() int64 {
	median := make([]int64, 0, medianTimeSpan)
	index := bIndex
	numNodes := 0
	for i := 0; i < medianTimeSpan && index != nil; i++ {
		median = append(median, int64(index.GetBlockTime()))
		index = index.Prev
		numNodes++
	}
	median = median[:numNodes]
	sort.Slice(median, func(i, j int) bool {
		return median[i] < median[j]
	})

	return median[numNodes/2]
}

// IsValid checks whether this block index entry is valid up to the passed validity
// level.
func (bIndex *BlockIndex) IsValid(upto uint32) bool {

	return false
}

// RaiseValidity Raise the validity level of this block index entry.
// Returns true if the validity was changed.
func (bIndex *BlockIndex) RaiseValidity(upto uint32) bool {

	return false
}

func (bIndex *BlockIndex) BuildSkip() {
	if bIndex.Prev != nil {
		bIndex.Skip = bIndex.Prev.GetAncestor(getSkipHeight(bIndex.Height))
	}
}

// Turn the lowest '1' bit in the binary representation of a number into a '0'.
func invertLowestOne(n int32) int32 {
	return n & (n - 1)
}

// getSkipHeight Compute what height to jump back to with the CBlockIndex::pskip pointer.
func getSkipHeight(height int32) int32 {
	if height < 2 {
		return 0
	}

	// Determine which height to jump back to. Any number strictly lower than
	// height is acceptable, but the following expression seems to perform well
	// in simulations (max 110 steps to go back up to 2**18 blocks).
	if (height & 1) > 0 {
		return invertLowestOne(invertLowestOne(height-1)) + 1
	}
	return invertLowestOne(height)
}

// GetAncestor efficiently find an ancestor of this block.
func (bIndex *BlockIndex) GetAncestor(height int32) *BlockIndex {
	if height > bIndex.Height || height < 0 {
		return nil
	}
	indexWalk := bIndex
	heightWalk := bIndex.Height
	for heightWalk > height {
		heightSkip := getSkipHeight(heightWalk)
		heightSkipPrev := getSkipHeight(heightWalk - 1)
		if indexWalk.Skip != nil && (heightSkip == height ||
			(heightSkip > height && !(heightSkipPrev < heightSkip-2 && heightSkipPrev >= height))) {
			// Only follow skip if prev->skip isn't better than skip->prev.
			indexWalk = indexWalk.Skip
			heightWalk = heightSkip
		} else {
			if indexWalk.Prev == nil {
				panic("The blockIndex pointer should not be nil")
			}
			indexWalk = indexWalk.Prev
			heightWalk--
		}
	}

	return indexWalk
}

func (bIndex *BlockIndex) String() string {
	hash := bIndex.GetBlockHash()
	return fmt.Sprintf("BlockIndex(pprev=%p, height=%d, merkle=%s, hashBlock=%s)\n", bIndex.Prev,
		bIndex.Height, bIndex.Header.MerkleRoot.String(), hash.String())
}

func NewBlockIndex(blkHeader *block.BlockHeader) *BlockIndex {
	blockIndex := new(BlockIndex)
	blockIndex.SetNull()
	blockIndex.Header = *blkHeader

	return blockIndex
}

<|endoftext|>


<commit_before>// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

// ExistsQuery is a query that only matches on documents that the field
// has a value in them.
//
// For more details, see:
// https://www.elastic.co/guide/en/elasticsearch/reference/6.2/query-dsl-exists-query.html
type ExistsQuery struct {
	name      string
	queryName string
}

// NewExistsQuery creates and initializes a new dis max query.
func NewExistsQuery(name string) *ExistsQuery {
	return &ExistsQuery{
		name: name,
	}
}

// QueryName sets the query name for the filter that can be used
// when searching for matched queries per hit.
func (q *ExistsQuery) QueryName(queryName string) *ExistsQuery {
	q.queryName = queryName
	return q
}

// Source returns the JSON serializable content for this query.
func (q *ExistsQuery) Source() (interface{}, error) {
	// {
	//   "exists" : {
	//     "field" : "user"
	//   }
	// }

	query := make(map[string]interface{})
	params := make(map[string]interface{})
	query["exists"] = params

	params["field"] = q.name
	if q.queryName != "" {
		params["_name"] = q.queryName
	}

	return query, nil
}
<commit_msg>Fix typo<commit_after>// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

// ExistsQuery is a query that only matches on documents that the field
// has a value in them.
//
// For more details, see:
// https://www.elastic.co/guide/en/elasticsearch/reference/6.2/query-dsl-exists-query.html
type ExistsQuery struct {
	name      string
	queryName string
}

// NewExistsQuery creates and initializes a new exists query.
func NewExistsQuery(name string) *ExistsQuery {
	return &ExistsQuery{
		name: name,
	}
}

// QueryName sets the query name for the filter that can be used
// when searching for matched queries per hit.
func (q *ExistsQuery) QueryName(queryName string) *ExistsQuery {
	q.queryName = queryName
	return q
}

// Source returns the JSON serializable content for this query.
func (q *ExistsQuery) Source() (interface{}, error) {
	// {
	//   "exists" : {
	//     "field" : "user"
	//   }
	// }

	query := make(map[string]interface{})
	params := make(map[string]interface{})
	query["exists"] = params

	params["field"] = q.name
	if q.queryName != "" {
		params["_name"] = q.queryName
	}

	return query, nil
}
<|endoftext|>