<commit_before>package bdiscord

import (
	"encoding/json"
	"errors"
	"regexp"
	"strings"
	"unicode"

	"github.com/bwmarrin/discordgo"
)

func (b *Bdiscord) getNick(user *discordgo.User) string {
	b.membersMutex.RLock()
	defer b.membersMutex.RUnlock()

	if member, ok := b.userMemberMap[user.ID]; ok {
		if member.Nick != "" {
			// Only return if nick is set.
			return member.Nick
		}
		// Otherwise return username.
		return user.Username
	}

	// If we didn't find nick, search for it.
	member, err := b.c.GuildMember(b.guildID, user.ID)
	if err != nil {
		b.Log.Warnf("Failed to fetch information for member %#v: %s", user, err)
		return user.Username
	} else if member == nil {
		b.Log.Warnf("Got no information for member %#v", user)
		return user.Username
	}
	b.userMemberMap[user.ID] = member
	b.nickMemberMap[member.User.Username] = member
	if member.Nick != "" {
		b.nickMemberMap[member.Nick] = member
		return member.Nick
	}
	return user.Username
}

func (b *Bdiscord) getGuildMemberByNick(nick string) (*discordgo.Member, error) {
	b.membersMutex.RLock()
	defer b.membersMutex.RUnlock()

	if member, ok := b.nickMemberMap[nick]; ok {
		return member, nil
	}
	return nil, errors.New("Couldn't find guild member with nick " + nick) // This will most likely get ignored by the caller
}

func (b *Bdiscord) getChannelID(name string) string {
	if strings.Contains(name, "/") {
		return b.getCategoryChannelID(name)
	}
	b.channelsMutex.RLock()
	defer b.channelsMutex.RUnlock()

	idcheck := strings.Split(name, "ID:")
	if len(idcheck) > 1 {
		return idcheck[1]
	}
	for _, channel := range b.channels {
		if channel.Name == name && channel.Type == discordgo.ChannelTypeGuildText {
			return channel.ID
		}
	}
	return ""
}

func (b *Bdiscord) getCategoryChannelID(name string) string {
	b.channelsMutex.RLock()
	defer b.channelsMutex.RUnlock()
	res := strings.Split(name, "/")
	// shouldn't happen because function should be only called from getChannelID
	if len(res) != 2 {
		return ""
	}
	catName, chanName := res[0], res[1]
	for _, channel := range b.channels {
		// if we have a parentID, lookup the name of that parent (category)
		// and if it matches return it
		if channel.Name == chanName && channel.ParentID != "" {
			for _, cat := range b.channels {
				if cat.ID == channel.ParentID && cat.Name == catName {
					return channel.ID
				}
			}
		}
	}
	return ""
}

func (b *Bdiscord) getChannelName(id string) string {
	b.channelsMutex.RLock()
	defer b.channelsMutex.RUnlock()

	for _, channel := range b.channels {
		if channel.ID == id {
			return b.getCategoryChannelName(channel.Name, channel.ParentID)
		}
	}
	return ""
}

func (b *Bdiscord) getCategoryChannelName(name, parentID string) string {
	var usesCat bool
	// do we have a category configuration in the channel config
	for _, c := range b.channelInfoMap {
		if strings.Contains(c.Name, "/") {
			usesCat = true
			break
		}
	}
	// configuration without category, return the normal channel name
	if !usesCat {
		return name
	}
	// create a category/channel response
	for _, c := range b.channels {
		if c.ID == parentID {
			name = c.Name + "/" + name
		}
	}
	return name
}

var (
	// See https://discordapp.com/developers/docs/reference#message-formatting.
	channelMentionRE = regexp.MustCompile("<#[0-9]+>")
	emojiRE          = regexp.MustCompile("<(:.*?:)[0-9]+>")
	userMentionRE    = regexp.MustCompile("@[^@\n]{1,32}")
)

func (b *Bdiscord) replaceChannelMentions(text string) string {
	replaceChannelMentionFunc := func(match string) string {
		channelID := match[2 : len(match)-1]
		channelName := b.getChannelName(channelID)

		// If we don't have the channel refresh our list.
		if channelName == "" {
			var err error
			b.channels, err = b.c.GuildChannels(b.guildID)
			if err != nil {
				return "#unknownchannel"
			}
			channelName = b.getChannelName(channelID)
		}
		return "#" + channelName
	}
	return channelMentionRE.ReplaceAllStringFunc(text, replaceChannelMentionFunc)
}

func (b *Bdiscord) replaceUserMentions(text string) string {
	replaceUserMentionFunc := func(match string) string {
		var (
			err      error
			member   *discordgo.Member
			username string
		)

		usernames := enumerateUsernames(match[1:])
		for _, username = range usernames {
			b.Log.Debugf("Testing mention: '%s'", username)
			member, err = b.getGuildMemberByNick(username)
			if err == nil {
				break
			}
		}
		if member == nil {
			return match
		}
		return strings.Replace(match, "@"+username, member.User.Mention(), 1)
	}
	return userMentionRE.ReplaceAllStringFunc(text, replaceUserMentionFunc)
}

func (b *Bdiscord) stripCustomoji(text string) string {
	return emojiRE.ReplaceAllString(text, `$1`)
}

func (b *Bdiscord) replaceAction(text string) (string, bool) {
	if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") {
		return text[1:], true
	}
	return text, false
}

// splitURL splits a webhookURL and returns the ID and token.
func (b *Bdiscord) splitURL(url string) (string, string) {
	const (
		expectedWebhookSplitCount = 7
		webhookIdxID              = 5
		webhookIdxToken           = 6
	)
	webhookURLSplit := strings.Split(url, "/")
	if len(webhookURLSplit) != expectedWebhookSplitCount {
		b.Log.Fatalf("%s is no correct discord WebhookURL", url)
	}
	return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken]
}

func enumerateUsernames(s string) []string {
	onlySpace := true
	for _, r := range s {
		if !unicode.IsSpace(r) {
			onlySpace = false
			break
		}
	}
	if onlySpace {
		return nil
	}

	var username, endSpace string
	var usernames []string
	skippingSpace := true
	for _, r := range s {
		if unicode.IsSpace(r) {
			if !skippingSpace {
				usernames = append(usernames, username)
				skippingSpace = true
			}
			endSpace += string(r)
			username += string(r)
		} else {
			endSpace = ""
			username += string(r)
			skippingSpace = false
		}
	}
	if endSpace == "" {
		usernames = append(usernames, username)
	}
	return usernames
}

// webhookExecute executes a webhook.
// webhookID: The ID of a webhook.
// token    : The auth token for the webhook
// wait	    : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
func (b *Bdiscord) webhookExecute(webhookID, token string, wait bool, data *discordgo.WebhookParams) (st *discordgo.Message, err error) {
	uri := discordgo.EndpointWebhookToken(webhookID, token)

	if wait {
		uri += "?wait=true"
	}
	response, err := b.c.RequestWithBucketID("POST", uri, data, discordgo.EndpointWebhookToken("", ""))
	if !wait || err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &st)
	if err != nil {
		return nil, discordgo.ErrJSONUnmarshal
	}

	return st, nil
}
<commit_msg>Fix regression (discord). Closes #864 (#866)<commit_after>package bdiscord

import (
	"encoding/json"
	"errors"
	"regexp"
	"strings"
	"unicode"

	"github.com/bwmarrin/discordgo"
)

func (b *Bdiscord) getNick(user *discordgo.User) string {
	b.membersMutex.RLock()
	defer b.membersMutex.RUnlock()

	if member, ok := b.userMemberMap[user.ID]; ok {
		if member.Nick != "" {
			// Only return if nick is set.
			return member.Nick
		}
		// Otherwise return username.
		return user.Username
	}

	// If we didn't find nick, search for it.
	member, err := b.c.GuildMember(b.guildID, user.ID)
	if err != nil {
		b.Log.Warnf("Failed to fetch information for member %#v: %s", user, err)
		return user.Username
	} else if member == nil {
		b.Log.Warnf("Got no information for member %#v", user)
		return user.Username
	}
	b.userMemberMap[user.ID] = member
	b.nickMemberMap[member.User.Username] = member
	if member.Nick != "" {
		b.nickMemberMap[member.Nick] = member
		return member.Nick
	}
	return user.Username
}

func (b *Bdiscord) getGuildMemberByNick(nick string) (*discordgo.Member, error) {
	b.membersMutex.RLock()
	defer b.membersMutex.RUnlock()

	if member, ok := b.nickMemberMap[nick]; ok {
		return member, nil
	}
	return nil, errors.New("Couldn't find guild member with nick " + nick) // This will most likely get ignored by the caller
}

func (b *Bdiscord) getChannelID(name string) string {
	if strings.Contains(name, "/") {
		return b.getCategoryChannelID(name)
	}
	b.channelsMutex.RLock()
	defer b.channelsMutex.RUnlock()

	idcheck := strings.Split(name, "ID:")
	if len(idcheck) > 1 {
		return idcheck[1]
	}
	for _, channel := range b.channels {
		if channel.Name == name && channel.Type == discordgo.ChannelTypeGuildText {
			return channel.ID
		}
	}
	return ""
}

func (b *Bdiscord) getCategoryChannelID(name string) string {
	b.channelsMutex.RLock()
	defer b.channelsMutex.RUnlock()
	res := strings.Split(name, "/")
	// shouldn't happen because function should be only called from getChannelID
	if len(res) != 2 {
		return ""
	}
	catName, chanName := res[0], res[1]
	for _, channel := range b.channels {
		// if we have a parentID, lookup the name of that parent (category)
		// and if it matches return it
		if channel.Name == chanName && channel.ParentID != "" {
			for _, cat := range b.channels {
				if cat.ID == channel.ParentID && cat.Name == catName {
					return channel.ID
				}
			}
		}
	}
	return ""
}

func (b *Bdiscord) getChannelName(id string) string {
	b.channelsMutex.RLock()
	defer b.channelsMutex.RUnlock()

	for _, channel := range b.channels {
		if channel.ID == id {
			return b.getCategoryChannelName(channel.Name, channel.ParentID)
		}
	}
	return ""
}

func (b *Bdiscord) getCategoryChannelName(name, parentID string) string {
	var usesCat bool
	// do we have a category configuration in the channel config
	for _, c := range b.channelInfoMap {
		if strings.Contains(c.Name, "/") {
			usesCat = true
			break
		}
	}
	// configuration without category, return the normal channel name
	if !usesCat {
		return name
	}
	// create a category/channel response
	for _, c := range b.channels {
		if c.ID == parentID {
			name = c.Name + "/" + name
		}
	}
	return name
}

var (
	// See https://discordapp.com/developers/docs/reference#message-formatting.
	channelMentionRE = regexp.MustCompile("<#[0-9]+>")
	emojiRE          = regexp.MustCompile("<(:.*?:)[0-9]+>")
	userMentionRE    = regexp.MustCompile("@[^@\n]{1,32}")
)

func (b *Bdiscord) replaceChannelMentions(text string) string {
	replaceChannelMentionFunc := func(match string) string {
		channelID := match[2 : len(match)-1]
		channelName := b.getChannelName(channelID)

		// If we don't have the channel refresh our list.
		if channelName == "" {
			var err error
			b.channels, err = b.c.GuildChannels(b.guildID)
			if err != nil {
				return "#unknownchannel"
			}
			channelName = b.getChannelName(channelID)
		}
		return "#" + channelName
	}
	return channelMentionRE.ReplaceAllStringFunc(text, replaceChannelMentionFunc)
}

func (b *Bdiscord) replaceUserMentions(text string) string {
	replaceUserMentionFunc := func(match string) string {
		var (
			err      error
			member   *discordgo.Member
			username string
		)

		usernames := enumerateUsernames(match[1:])
		for _, username = range usernames {
			b.Log.Debugf("Testing mention: '%s'", username)
			member, err = b.getGuildMemberByNick(username)
			if err == nil {
				break
			}
		}
		if member == nil {
			return match
		}
		return strings.Replace(match, "@"+username, member.User.Mention(), 1)
	}
	return userMentionRE.ReplaceAllStringFunc(text, replaceUserMentionFunc)
}

func (b *Bdiscord) stripCustomoji(text string) string {
	return emojiRE.ReplaceAllString(text, `$1`)
}

func (b *Bdiscord) replaceAction(text string) (string, bool) {
	if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") {
		return text[1 : len(text)-1], true
	}
	return text, false
}

// splitURL splits a webhookURL and returns the ID and token.
func (b *Bdiscord) splitURL(url string) (string, string) {
	const (
		expectedWebhookSplitCount = 7
		webhookIdxID              = 5
		webhookIdxToken           = 6
	)
	webhookURLSplit := strings.Split(url, "/")
	if len(webhookURLSplit) != expectedWebhookSplitCount {
		b.Log.Fatalf("%s is no correct discord WebhookURL", url)
	}
	return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken]
}

func enumerateUsernames(s string) []string {
	onlySpace := true
	for _, r := range s {
		if !unicode.IsSpace(r) {
			onlySpace = false
			break
		}
	}
	if onlySpace {
		return nil
	}

	var username, endSpace string
	var usernames []string
	skippingSpace := true
	for _, r := range s {
		if unicode.IsSpace(r) {
			if !skippingSpace {
				usernames = append(usernames, username)
				skippingSpace = true
			}
			endSpace += string(r)
			username += string(r)
		} else {
			endSpace = ""
			username += string(r)
			skippingSpace = false
		}
	}
	if endSpace == "" {
		usernames = append(usernames, username)
	}
	return usernames
}

// webhookExecute executes a webhook.
// webhookID: The ID of a webhook.
// token    : The auth token for the webhook
// wait	    : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
func (b *Bdiscord) webhookExecute(webhookID, token string, wait bool, data *discordgo.WebhookParams) (st *discordgo.Message, err error) {
	uri := discordgo.EndpointWebhookToken(webhookID, token)

	if wait {
		uri += "?wait=true"
	}
	response, err := b.c.RequestWithBucketID("POST", uri, data, discordgo.EndpointWebhookToken("", ""))
	if !wait || err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &st)
	if err != nil {
		return nil, discordgo.ErrJSONUnmarshal
	}

	return st, nil
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

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

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

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

package console

import (
	"fmt"
	"os"
	"unsafe"

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

const (
	cmdTcGet = unix.TCGETS
	cmdTcSet = unix.TCSETS
)

// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
// unlockpt should be called before opening the slave side of a pty.
func unlockpt(f *os.File) error {
	var u int32
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 {
		return err
	}
	return nil
}

// ptsname retrieves the name of the first available pts for the given master.
func ptsname(f *os.File) (string, error) {
	var u uint32
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 {
		return "", err
	}
	return fmt.Sprintf("/dev/pts/%d", u), nil
}
<commit_msg>tc_linux.go: add a warning to not change the code<commit_after>/*
   Copyright The containerd Authors.

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

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

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

package console

import (
	"fmt"
	"os"
	"unsafe"

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

const (
	cmdTcGet = unix.TCGETS
	cmdTcSet = unix.TCSETS
)

// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
// unlockpt should be called before opening the slave side of a pty.
func unlockpt(f *os.File) error {
	var u int32
	// XXX do not use unix.IoctlSetPointerInt here, see commit dbd69c59b81.
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 {
		return err
	}
	return nil
}

// ptsname retrieves the name of the first available pts for the given master.
func ptsname(f *os.File) (string, error) {
	var u uint32
	// XXX do not use unix.IoctlGetInt here, see commit dbd69c59b81.
	if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 {
		return "", err
	}
	return fmt.Sprintf("/dev/pts/%d", u), nil
}
<|endoftext|>


<commit_before>package main

import (
  "flag"
	"fmt"
	"text/template"
	"os"
  "io/ioutil"
  "bufio"
  "gopkg.in/yaml.v2"
  "github.com/winkapp/libclc"
)

type File struct {
  Path string
  Content string
  Owner string
  Permissions string
}

type CloudConfig struct {
  DiscoveryUrl string
  Files []*File
}

var template_dir string
var root string
var config_file string

func main() {
  // Figure out which directory we are going to prep files for
  template_def := os.ExpandEnv("$GOPATH/src/github.com/winkapp/clc/templates")
  flag.StringVar(&template_dir, "templates", template_def, "Your templates.")
  flag.StringVar(&root, "root", "./", "Directory for configs and output.")
  flag.StringVar(&config_file, "config", "clc.yaml", "Optional config file.")
  flag.Parse()
  command := flag.Arg(0)

  switch command {
  case "cc": cc(root)
  case "vagrant": vagrant(root)
  case "units": units(root)
  case "new": newCluster(root)
  }

}

func newCluster(path string) {
  cc(root)
  vagrant(root)
  units(root)
  return
}

func vagrant(path string) {
  ud(path)
  copyFile(path + "/Vagrantfile", template_dir + "/Vagrantfile.template")
  copyFile(path + "/config.rb", template_dir + "/config.rb.template")
  return
}

func units(path string) {
  unitsYaml := getFileBytes(path + "/units.yaml")
  var units libclc.UnitConfig
  err := yaml.Unmarshal(unitsYaml, &units)
  checkError(err)
  for _, service := range units.Units {
    t := unitsTemplate(service)
    fileName := unitFileName(service)

    f, err := os.Create(path + "/units/" + fileName)
    checkError(err)
    defer f.Close()
    w := bufio.NewWriter(f)
    libclc.MakeUnit(t, service, w)
    checkError(err)
    w.Flush()
  }
}

func ud(path string) {
  // TODO: Open the files document for file includes
  file1 := File{
    Content: getFile("./etcd_env.sh"),
    Path: "/home/core/etcd_env.sh",
    Owner: "core:core",
    Permissions: "744",
  }

  data := CloudConfig{
    Files: []*File{&file1},
  }

  t := udTemplate(data)
  err := t.Execute(os.Stdout, data)
  checkError(err)
}

func cc(path string) {
  data := ccData(path)
  t := ccTemplate(data)
  err := t.Execute(os.Stdout, data)
	checkError(err)
}

func ccData(path string) (data CloudConfig) {
  // Open the files document for file includes
  file1 := File{
    Content: getFile("./etcd_env.sh"),
    Path: "/home/core/etcd_env.sh",
    Owner: "core:core",
    Permissions: "744",
  }

  // Open the document for the discovery url
  discovery_url := getFile(path + "/discovery_url")

  // Include files on cloud config
  data = CloudConfig{
    DiscoveryUrl: discovery_url,
    Files: []*File{&file1},
  }
  return
}

func unitsTemplate(data *libclc.Unit) (t *template.Template) {
  t = getTemplate("Service Template", "service.template")
  return
}

func ccTemplate(data CloudConfig) (t *template.Template) {
  t = getTemplate("Cloud Config Template", "cloud-config.template")
  return
}

func udTemplate(data CloudConfig) (t *template.Template) {
  t = getTemplate("User Data Template", "user-data.template")
  return
}

func unitFileName(service *libclc.Unit) string {
  switch service.Type {
  case "single":
    service.Filename = (service.Name + ".service")
  case "multi":
    service.Filename = (service.Name + "@.service")
  }

  return service.Filename
}

func addFile(path string, f os.FileInfo, err error) error {
  fmt.Printf("Visited: %s\n", path)
  return nil
}

func getFileBytes(path string) []byte {
  dat, err := ioutil.ReadFile(path)
  checkError(err)
  return dat
}

func getFile(path string) string {
  return string(getFileBytes(path))
}

func copyFile(dstPath string, srcPath string) {
  src, err := ioutil.ReadFile(srcPath)
  checkError(err)
  mode := int(0644)
  err = ioutil.WriteFile(dstPath, src, os.FileMode(mode))
  checkError(err)
  return
}

func getTemplate(name string, filename string) (t *template.Template) {
  templ := getFile(template_dir + "/" + filename)

  t = template.New(name)
  t, err := t.Parse(templ)
  checkError(err)
  return
}

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error:", err.Error())
		os.Exit(1)
	}
}
<commit_msg>Factor out more unit writing logic to libclc.<commit_after>package main

import (
  "flag"
	"fmt"
	"text/template"
	"os"
  "io/ioutil"
  "gopkg.in/yaml.v2"
  "github.com/winkapp/libclc"
)

type File struct {
  Path string
  Content string
  Owner string
  Permissions string
}

type CloudConfig struct {
  DiscoveryUrl string
  Files []*File
}

var template_dir string
var root string
var config_file string

func main() {
  // Figure out which directory we are going to prep files for
  template_def := os.ExpandEnv("$GOPATH/src/github.com/winkapp/clc/templates")
  flag.StringVar(&template_dir, "templates", template_def, "Your templates.")
  flag.StringVar(&root, "root", "./", "Directory for configs and output.")
  flag.StringVar(&config_file, "config", "clc.yaml", "Optional config file.")
  flag.Parse()
  command := flag.Arg(0)

  switch command {
  case "cc": cc(root)
  case "vagrant": vagrant(root)
  case "units": units(root)
  case "new": newCluster(root)
  }

}

func newCluster(path string) {
  cc(root)
  vagrant(root)
  units(root)
  return
}

func vagrant(path string) {
  ud(path)
  copyFile(path + "/Vagrantfile", template_dir + "/Vagrantfile.template")
  copyFile(path + "/config.rb", template_dir + "/config.rb.template")
  return
}

func units(path string) {
  unitsYaml := getFileBytes(path + "/units.yaml")
  var units libclc.UnitConfig
  err := yaml.Unmarshal(unitsYaml, &units)
  checkError(err)
  t := unitsTemplate()
  err = libclc.WriteUnits(&units, t, path + "/units")
  checkError(err)
}

func ud(path string) {
  // TODO: Open the files document for file includes
  file1 := File{
    Content: getFile("./etcd_env.sh"),
    Path: "/home/core/etcd_env.sh",
    Owner: "core:core",
    Permissions: "744",
  }

  data := CloudConfig{
    Files: []*File{&file1},
  }

  t := udTemplate(data)
  err := t.Execute(os.Stdout, data)
  checkError(err)
}

func cc(path string) {
  data := ccData(path)
  t := ccTemplate(data)
  err := t.Execute(os.Stdout, data)
	checkError(err)
}

func ccData(path string) (data CloudConfig) {
  // Open the files document for file includes
  file1 := File{
    Content: getFile("./etcd_env.sh"),
    Path: "/home/core/etcd_env.sh",
    Owner: "core:core",
    Permissions: "744",
  }

  // Open the document for the discovery url
  discovery_url := getFile(path + "/discovery_url")

  // Include files on cloud config
  data = CloudConfig{
    DiscoveryUrl: discovery_url,
    Files: []*File{&file1},
  }
  return
}

func unitsTemplate() (t *template.Template) {
  t = getTemplate("Service Template", "service.template")
  return
}

func ccTemplate(data CloudConfig) (t *template.Template) {
  t = getTemplate("Cloud Config Template", "cloud-config.template")
  return
}

func udTemplate(data CloudConfig) (t *template.Template) {
  t = getTemplate("User Data Template", "user-data.template")
  return
}

func addFile(path string, f os.FileInfo, err error) error {
  fmt.Printf("Visited: %s\n", path)
  return nil
}

func getFileBytes(path string) []byte {
  dat, err := ioutil.ReadFile(path)
  checkError(err)
  return dat
}

func getFile(path string) string {
  return string(getFileBytes(path))
}

func copyFile(dstPath string, srcPath string) {
  src, err := ioutil.ReadFile(srcPath)
  checkError(err)
  mode := int(0644)
  err = ioutil.WriteFile(dstPath, src, os.FileMode(mode))
  checkError(err)
  return
}

func getTemplate(name string, filename string) (t *template.Template) {
  templ := getFile(template_dir + "/" + filename)

  t = template.New(name)
  t, err := t.Parse(templ)
  checkError(err)
  return
}

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error:", err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Package fasttemplate implements simple and fast template library.
//
// Fasttemplate is faster than text/template, strings.Replace
// and strings.Replacer.
//
// Fasttemplate ideally fits for fast and simple placeholders' substitutions.
package fasttemplate

import (
	"bytes"
	"fmt"
	"io"
	"sync"
)

// Template implements simple template engine, which can be used for fast
// tags' (aka placeholders) substitution.
type Template struct {
	template string
	startTag string
	endTag   string

	texts           [][]byte
	tags            []string
	bytesBufferPool sync.Pool
}

// New parses the given template using the given startTag and endTag
// as tag start and tag end.
//
// The returned template can be executed by concurrently running goroutines
// using Execute* methods.
//
// New panics if the given template cannot be parsed. Use NewTemplate instead
// if template may contain errors.
func New(template, startTag, endTag string) *Template {
	t, err := NewTemplate(template, startTag, endTag)
	if err != nil {
		panic(err)
	}
	return t
}

// NewTemplate parses the given template using the given startTag and endTag
// as tag start and tag end.
//
// The returned template can be executed by concurrently running goroutines
// using Execute* methods.
func NewTemplate(template, startTag, endTag string) (*Template, error) {
	var t Template
	t.bytesBufferPool.New = newBytesBuffer
	err := t.Reset(template, startTag, endTag)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func newBytesBuffer() interface{} {
	return &bytes.Buffer{}
}

// TagFunc can be used as a substitution value in the map passed to Execute*.
// Execute* functions pass tag (placeholder) name in 'tag' argument.
//
// TagFunc must be safe to call from concurrently running goroutines.
//
// TagFunc must write contents to w and return the number of bytes written.
type TagFunc func(w io.Writer, tag string) (int, error)

// Reset resets the template t to new one defined by
// template, startTag and endTag.
//
// Reset allows Template object re-use.
//
// Reset may be called only if no other goroutines call t methods at the moment.
func (t *Template) Reset(template, startTag, endTag string) error {
	// Keep these vars in t, so GC won't collect them and won't break
	// vars derived via unsafe*
	t.template = template
	t.startTag = startTag
	t.endTag = endTag
	t.texts = t.texts[:0]
	t.tags = t.tags[:0]

	if len(startTag) == 0 {
		panic("startTag cannot be empty")
	}
	if len(endTag) == 0 {
		panic("endTag cannot be empty")
	}

	s := unsafeString2Bytes(template)
	a := unsafeString2Bytes(startTag)
	b := unsafeString2Bytes(endTag)

	tagsCount := bytes.Count(s, a)
	if tagsCount == 0 {
		return nil
	}

	if tagsCount+1 > cap(t.texts) {
		t.texts = make([][]byte, 0, tagsCount+1)
	}
	if tagsCount > cap(t.tags) {
		t.tags = make([]string, 0, tagsCount)
	}

	for {
		n := bytes.Index(s, a)
		if n < 0 {
			t.texts = append(t.texts, s)
			break
		}
		t.texts = append(t.texts, s[:n])

		s = s[n+len(a):]
		n = bytes.Index(s, b)
		if n < 0 {
			return fmt.Errorf("Cannot find end tag=%q in the template=%q starting from %q", endTag, template, s)
		}

		t.tags = append(t.tags, unsafeBytes2String(s[:n]))
		s = s[n+len(b):]
	}

	return nil
}

// ExecuteFunc calls f on each template tag (placeholder) occurrence.
//
// Returns the number of bytes written to w.
func (t *Template) ExecuteFunc(w io.Writer, f TagFunc) (int64, error) {
	var nn int64

	n := len(t.texts) - 1
	if n == -1 {
		ni, err := w.Write(unsafeString2Bytes(t.template))
		return int64(ni), err
	}

	for i := 0; i < n; i++ {
		ni, err := w.Write(t.texts[i])
		if err != nil {
			return nn, err
		}
		nn += int64(ni)

		if ni, err = f(w, t.tags[i]); err != nil {
			return nn, err
		}
		nn += int64(ni)
	}
	ni, err := w.Write(t.texts[n])
	if err != nil {
		return nn, err
	}
	nn += int64(ni)
	return nn, nil
}

// Execute substitutes template tags (placeholders) with the corresponding
// values from the map m and writes the result to the given writer w.
//
// Substitution map m may contain values with the following types:
//   * []byte - the fastest value type
//   * string - convenient value type
//   * TagFunc - flexible value type
//
// Returns the number of bytes written to w.
func (t *Template) Execute(w io.Writer, m map[string]interface{}) (int64, error) {
	return t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
}

// ExecuteFuncString call f on each template tag (placeholder) occurrence
// and substitutes it with the data written to TagFunc's w.
//
// Returns the resulting string.
func (t *Template) ExecuteFuncString(f TagFunc) string {
	w := t.bytesBufferPool.Get().(*bytes.Buffer)
	if _, err := t.ExecuteFunc(w, f); err != nil {
		panic(fmt.Sprintf("unexpected error: %s", err))
	}
	s := string(w.Bytes())
	w.Reset()
	t.bytesBufferPool.Put(w)
	return s
}

// ExecuteString substitutes template tags (placeholders) with the corresponding
// values from the map m and returns the result.
//
// Substitution map m may contain values with the following types:
//   * []byte - the fastest value type
//   * string - convenient value type
//   * TagFunc - flexible value type
//
func (t *Template) ExecuteString(m map[string]interface{}) string {
	return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
}

func stdTagFunc(w io.Writer, tag string, m map[string]interface{}) (int, error) {
	v := m[tag]
	if v == nil {
		return 0, nil
	}
	switch value := v.(type) {
	case []byte:
		return w.Write(value)
	case string:
		return w.Write([]byte(value))
	case TagFunc:
		return value(w, tag)
	default:
		panic(fmt.Sprintf("tag=%q contains unexpected value type=%#v. Expected []byte, string or TagFunc", tag, v))
	}
}
<commit_msg>Allow calling Template.Reset on uninitialized Template<commit_after>// Package fasttemplate implements simple and fast template library.
//
// Fasttemplate is faster than text/template, strings.Replace
// and strings.Replacer.
//
// Fasttemplate ideally fits for fast and simple placeholders' substitutions.
package fasttemplate

import (
	"bytes"
	"fmt"
	"io"
	"sync"
)

// Template implements simple template engine, which can be used for fast
// tags' (aka placeholders) substitution.
type Template struct {
	template string
	startTag string
	endTag   string

	texts           [][]byte
	tags            []string
	bytesBufferPool sync.Pool
}

// New parses the given template using the given startTag and endTag
// as tag start and tag end.
//
// The returned template can be executed by concurrently running goroutines
// using Execute* methods.
//
// New panics if the given template cannot be parsed. Use NewTemplate instead
// if template may contain errors.
func New(template, startTag, endTag string) *Template {
	t, err := NewTemplate(template, startTag, endTag)
	if err != nil {
		panic(err)
	}
	return t
}

// NewTemplate parses the given template using the given startTag and endTag
// as tag start and tag end.
//
// The returned template can be executed by concurrently running goroutines
// using Execute* methods.
func NewTemplate(template, startTag, endTag string) (*Template, error) {
	var t Template
	err := t.Reset(template, startTag, endTag)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func newBytesBuffer() interface{} {
	return &bytes.Buffer{}
}

// TagFunc can be used as a substitution value in the map passed to Execute*.
// Execute* functions pass tag (placeholder) name in 'tag' argument.
//
// TagFunc must be safe to call from concurrently running goroutines.
//
// TagFunc must write contents to w and return the number of bytes written.
type TagFunc func(w io.Writer, tag string) (int, error)

// Reset resets the template t to new one defined by
// template, startTag and endTag.
//
// Reset allows Template object re-use.
//
// Reset may be called only if no other goroutines call t methods at the moment.
func (t *Template) Reset(template, startTag, endTag string) error {
	// Keep these vars in t, so GC won't collect them and won't break
	// vars derived via unsafe*
	t.bytesBufferPool.New = newBytesBuffer
	t.template = template
	t.startTag = startTag
	t.endTag = endTag
	t.texts = t.texts[:0]
	t.tags = t.tags[:0]

	if len(startTag) == 0 {
		panic("startTag cannot be empty")
	}
	if len(endTag) == 0 {
		panic("endTag cannot be empty")
	}

	s := unsafeString2Bytes(template)
	a := unsafeString2Bytes(startTag)
	b := unsafeString2Bytes(endTag)

	tagsCount := bytes.Count(s, a)
	if tagsCount == 0 {
		return nil
	}

	if tagsCount+1 > cap(t.texts) {
		t.texts = make([][]byte, 0, tagsCount+1)
	}
	if tagsCount > cap(t.tags) {
		t.tags = make([]string, 0, tagsCount)
	}

	for {
		n := bytes.Index(s, a)
		if n < 0 {
			t.texts = append(t.texts, s)
			break
		}
		t.texts = append(t.texts, s[:n])

		s = s[n+len(a):]
		n = bytes.Index(s, b)
		if n < 0 {
			return fmt.Errorf("Cannot find end tag=%q in the template=%q starting from %q", endTag, template, s)
		}

		t.tags = append(t.tags, unsafeBytes2String(s[:n]))
		s = s[n+len(b):]
	}

	return nil
}

// ExecuteFunc calls f on each template tag (placeholder) occurrence.
//
// Returns the number of bytes written to w.
func (t *Template) ExecuteFunc(w io.Writer, f TagFunc) (int64, error) {
	var nn int64

	n := len(t.texts) - 1
	if n == -1 {
		ni, err := w.Write(unsafeString2Bytes(t.template))
		return int64(ni), err
	}

	for i := 0; i < n; i++ {
		ni, err := w.Write(t.texts[i])
		if err != nil {
			return nn, err
		}
		nn += int64(ni)

		if ni, err = f(w, t.tags[i]); err != nil {
			return nn, err
		}
		nn += int64(ni)
	}
	ni, err := w.Write(t.texts[n])
	if err != nil {
		return nn, err
	}
	nn += int64(ni)
	return nn, nil
}

// Execute substitutes template tags (placeholders) with the corresponding
// values from the map m and writes the result to the given writer w.
//
// Substitution map m may contain values with the following types:
//   * []byte - the fastest value type
//   * string - convenient value type
//   * TagFunc - flexible value type
//
// Returns the number of bytes written to w.
func (t *Template) Execute(w io.Writer, m map[string]interface{}) (int64, error) {
	return t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
}

// ExecuteFuncString call f on each template tag (placeholder) occurrence
// and substitutes it with the data written to TagFunc's w.
//
// Returns the resulting string.
func (t *Template) ExecuteFuncString(f TagFunc) string {
	w := t.bytesBufferPool.Get().(*bytes.Buffer)
	if _, err := t.ExecuteFunc(w, f); err != nil {
		panic(fmt.Sprintf("unexpected error: %s", err))
	}
	s := string(w.Bytes())
	w.Reset()
	t.bytesBufferPool.Put(w)
	return s
}

// ExecuteString substitutes template tags (placeholders) with the corresponding
// values from the map m and returns the result.
//
// Substitution map m may contain values with the following types:
//   * []byte - the fastest value type
//   * string - convenient value type
//   * TagFunc - flexible value type
//
func (t *Template) ExecuteString(m map[string]interface{}) string {
	return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
}

func stdTagFunc(w io.Writer, tag string, m map[string]interface{}) (int, error) {
	v := m[tag]
	if v == nil {
		return 0, nil
	}
	switch value := v.(type) {
	case []byte:
		return w.Write(value)
	case string:
		return w.Write([]byte(value))
	case TagFunc:
		return value(w, tag)
	default:
		panic(fmt.Sprintf("tag=%q contains unexpected value type=%#v. Expected []byte, string or TagFunc", tag, v))
	}
}
<|endoftext|>


<commit_before>package main

const entryTmpl = `
entity "{{ .Name }}" {
{{- if .Comment.Valid }}
  {{ .Comment.String }}
  ..
{{- end }}
{{- range .Columns }}
  {{- if .IsPrimaryKey }}
  + {{ .Name }}:{{ .DataType }} [PK]{{if .IsForeignKey }}[FK]{{end}}{{- if .Comment.Valid }} : {{ .Comment.String }}{{- end }}
  {{- end }}
{{- end }}
  --
{{- range .Columns }}
  {{- if not .IsPrimaryKey }}
  {{if .NotNull}}*{{end}}{{ .Name }}:{{ .DataType }} {{if .IsForeignKey}}[FK]{{end}} {{- if .Comment.Valid }} : {{ .Comment.String }}{{- end }}
  {{- end }}
{{- end }}
}
`

const relationTmpl = `
{{ if .IsOneToOne }} {{ .SourceTableName }} ||-|| {{ .TargetTableName }}{{else}} {{ .SourceTableName }} }-- {{ .TargetTableName }}{{end}}
`
<commit_msg>Use DDLType<commit_after>package main

const entryTmpl = `
entity "{{ .Name }}" {
{{- if .Comment.Valid }}
  {{ .Comment.String }}
  ..
{{- end }}
{{- range .Columns }}
  {{- if .IsPrimaryKey }}
  + {{ .Name }}:{{ .DDLType }} [PK]{{if .IsForeignKey }}[FK]{{end}}{{- if .Comment.Valid }} : {{ .Comment.String }}{{- end }}
  {{- end }}
{{- end }}
  --
{{- range .Columns }}
  {{- if not .IsPrimaryKey }}
  {{if .NotNull}}*{{end}}{{ .Name }}:{{ .DDLType }} {{if .IsForeignKey}}[FK]{{end}} {{- if .Comment.Valid }} : {{ .Comment.String }}{{- end }}
  {{- end }}
{{- end }}
}
`

const relationTmpl = `
{{ if .IsOneToOne }} {{ .SourceTableName }} ||-|| {{ .TargetTableName }}{{else}} {{ .SourceTableName }} }-- {{ .TargetTableName }}{{end}}
`
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/go-ini/ini"
)

func main() {

	args := os.Args[1:]
	text2analize := ""
	attribts := new(attributes)
	setupfile := "setup.ini"

	//Carregar setup através do .ini
	cfg, err := ini.Load(setupfile)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error:", err)
		os.Exit(1)
	}

	err = cfg.Section("attributes").MapTo(attribts)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error:", err)
		os.Exit(1)
	}

	/*Caso existam argumentos de entrada,
	se comporta apenas como aplicação de console,
	caso contrário se comporta como serviço de api web*/
	if len(args) != 0 {
		for i := 0; i < len(args); i++ {
			if args[i] == "-m" {
				attribts.Method = args[i+1]
				i = i + 1
			} else {
				text2analize += args[i] + " "
			}

		}
		log.Println(execNlpnetCommand(attribts, text2analize))

	} else {
		http.HandleFunc("/parser", func(w http.ResponseWriter, r *http.Request) {

			/* Valida as entradas e carrega a estrutura */
			if method := r.FormValue("method"); method != "" {
				attribts.Method = method
			}
			if txt := r.FormValue("txt"); txt != "" {
				text2analize = txt
			}

			/* Retorna a mensagem analisada */
			io.WriteString(w, execNlpnetCommand(attribts, text2analize))

		})
		fmt.Printf("nlpnet2go running at: %s\n", attribts.Port)
		http.ListenAndServe(":"+attribts.Port, nil)

	}

}

func execNlpnetCommand(attribts *attributes, text2analize string) string {

	cmdArgs := []string{attribts.Nlpnet2gopy, "-t", text2analize, "-m", attribts.Method}
	cmd := exec.Command(attribts.CmdName, cmdArgs...)

	cmdReader, err := cmd.Output()
	if err != nil {
		fmt.Printf("Error: [%s]", err.Error())
		os.Exit(1)
	}

	/* Conversão para JSON */
	var result string
	if attribts.Method == "pos" {
		replacer := strings.NewReplacer("(u'", "{\"", "', u'", "\": \"", "')", "\"}")
		result = replacer.Replace(string(cmdReader))
	} else {
		result = string(cmdReader)
	}
	return result

}

type attributes struct {
	Method      string `ini:"method"`
	Port        string `ini:"port"`
	CmdName     string `ini:"cmdName"`
	Nlpnet2gopy string `ini:"nlpnet2gopy"`
	Setdatadir  string `ini:"setdatadir"`
}
<commit_msg>Retorna um json por chave valor<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/go-ini/ini"
)

func main() {

	args := os.Args[1:]
	text2analize := ""
	attribts := new(attributes)
	setupfile := "setup.ini"

	//Carregar setup através do .ini
	cfg, err := ini.Load(setupfile)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error:", err)
		os.Exit(1)
	}

	err = cfg.Section("attributes").MapTo(attribts)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error:", err)
		os.Exit(1)
	}

	/*Caso existam argumentos de entrada,
	se comporta apenas como aplicação de console,
	caso contrário se comporta como serviço de api web*/
	if len(args) != 0 {
		for i := 0; i < len(args); i++ {
			if args[i] == "-m" {
				attribts.Method = args[i+1]
				i = i + 1
			} else {
				text2analize += args[i] + " "
			}

		}
		log.Println(execNlpnetCommand(attribts, text2analize))

	} else {
		http.HandleFunc("/parser", func(w http.ResponseWriter, r *http.Request) {

			/* Valida as entradas e carrega a estrutura */
			if method := r.FormValue("method"); method != "" {
				attribts.Method = method
			}
			if txt := r.FormValue("txt"); txt != "" {
				text2analize = txt
			}

			/* Retorna a mensagem analisada */
			io.WriteString(w, execNlpnetCommand(attribts, text2analize))

		})
		fmt.Printf("nlpnet2go running at: %s\n", attribts.Port)
		http.ListenAndServe(":"+attribts.Port, nil)

	}

}

func execNlpnetCommand(attribts *attributes, text2analize string) string {

	cmdArgs := []string{attribts.Nlpnet2gopy, "-t", text2analize, "-m", attribts.Method}
	cmd := exec.Command(attribts.CmdName, cmdArgs...)

	cmdReader, err := cmd.Output()
	if err != nil {
		fmt.Printf("Error: [%s]", err.Error())
		os.Exit(1)
	}

	/* Conversão para JSON */
	var result string
	if attribts.Method == "pos" {
		//fmt.Printf("%s\n", string(cmdReader))
		/*
			Os replaces abaixo são para tratar o retorno do nlpnet.
			Exemplo: [[(u'o', u'ART'), (u'rato', u'N'), (u'roeu', u'V'), (u'a', u'ART'), (u'roupa', u'N'), (u'do', u'PREP+ART'), (u'rei', u'N'), (u'de', u'PREP'), (u'roma', u'N'), (u'com', u'PREP'), (u'queijo', u'N')]]
		*/
		replacer := strings.NewReplacer("[", "", "]", "", "(u'", "", " u'", "", "'", "", "),", ");")
		replacerInsider := strings.NewReplacer("(", "", ")", "")
		result = replacer.Replace(string(cmdReader))
		retornos := strings.Split(result, ";")
		result = ""
		ret := Retorno{}
		arrRetornoItems := []RetornoItem{}
		for _, item := range retornos {
			item = replacerInsider.Replace(item)
			chaveValores := strings.Split(item, ",")
			tipo := strings.TrimSpace(chaveValores[1])
			valor := strings.TrimSpace(chaveValores[0])
			if tipo == "N" || tipo == "NPROP" {
				if valor == "queijo" {
					tipo = "ALIMENTO"
				}
			}
			retItem := RetornoItem{Chave: tipo, Valor: valor}
			arrRetornoItems = append(arrRetornoItems, retItem)
			fmt.Printf("Tipo: [%s] Valor: [%s]\n", tipo, valor)
		}
		ret.RetornoItems = arrRetornoItems
		jsonret, err := json.Marshal(ret)
		if err != nil {
			return "Erro na geracao do JSON. Erro: " + err.Error()
		}
		return string(jsonret)
	} else {
		return string(cmdReader)
	}
	return ""

}

type attributes struct {
	Method      string `ini:"method"`
	Port        string `ini:"port"`
	CmdName     string `ini:"cmdName"`
	Nlpnet2gopy string `ini:"nlpnet2gopy"`
	Setdatadir  string `ini:"setdatadir"`
}

type Retorno struct {
	RetornoItems []RetornoItem `json:"items"`
}
type RetornoItem struct {
	Chave string `json:"chave"`
	Valor string `json:"valor"`
}
<|endoftext|>


<commit_before>package asciibrot

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

type winsize struct {
	Row uint16
	Col uint16
}

// Screen buffer
// Do not write to buffer directly, use package Print, Printf, Println functions instead.
var Screen *bytes.Buffer = new(bytes.Buffer)
var output *bufio.Writer = bufio.NewWriter(os.Stdout)

func init() {
	// Clear console
	output.WriteString("\033[2J")
	// Remove blinking cursor
	output.WriteString("\033[?25l")
}

// Get console width
func Width() int {
	ws, err := getWinsize()

	if err != nil {
		return -1
	}

	return int(ws.Row)
}

// Get console height
func Height() int {
	ws, err := getWinsize()
	if err != nil {
		return -1
	}
	return int(ws.Col)
}

// Flush buffer and ensure that it will not overflow screen
func Flush() {
	for idx, str := range strings.Split(Screen.String(), "\n") {
		if idx > Height() {
			return
		}

		output.WriteString(str + "\n")
	}

	output.Flush()
	Screen.Reset()
}

// Move cursor to given position
func MoveCursor(x int, y int) {
	fmt.Fprintf(Screen, "\033[%d;%dH", x, y)
}
<commit_msg>Support windows<commit_after>package asciibrot

import (
	"bufio"
	"bytes"
	"fmt"
	"strings"

	"github.com/mattn/go-colorable"
)

type winsize struct {
	Row uint16
	Col uint16
}

// Screen buffer
// Do not write to buffer directly, use package Print, Printf, Println functions instead.
var Screen *bytes.Buffer = new(bytes.Buffer)
var output *bufio.Writer = bufio.NewWriter(colorable.NewColorableStdout())

func init() {
	// Clear console
	output.WriteString("\033[2J")
	// Remove blinking cursor
	output.WriteString("\033[?25l")
}

// Get console width
func Width() int {
	ws, err := getWinsize()

	if err != nil {
		return -1
	}

	return int(ws.Row)
}

// Get console height
func Height() int {
	ws, err := getWinsize()
	if err != nil {
		return -1
	}
	return int(ws.Col)
}

// Flush buffer and ensure that it will not overflow screen
func Flush() {
	for idx, str := range strings.Split(Screen.String(), "\n") {
		if idx > Height() {
			return
		}

		output.WriteString(str + "\n")
	}

	output.Flush()
	Screen.Reset()
}

// Move cursor to given position
func MoveCursor(x int, y int) {
	fmt.Fprintf(Screen, "\033[%d;%dH", x, y)
}
<|endoftext|>


<commit_before>package QesyDb

import(
    "database/sql"
    "fmt"
    "strings"
    "log"
    _"github.com/go-sql-driver/mysql"
    "reflect"
    "strconv"
    "time"
)

var Db *sql.DB

type Model struct{
    Cond interface{}
    Insert map[string]string
    Update map[string]string
    Field string
    Table string
    Index string
    Limit interface{}
    Sort string
    Fetch int
}

// Connect  is a method with a sql.
func Connect(connStr string){
    sqlDb, err := sql.Open("mysql", connStr)
    if(err != nil){
        log.Fatal("mysql connect error")
    }
    err = sqlDb.Ping()
    if(err != nil){
        log.Fatal("mysql ping error")
    }
	fmt.Println("mysql connect sueccss")
    Db = sqlDb
}

// ExecSelectIndex  is a method with a sql.
func (m *Model) ExecSelectIndex() (map[string]map[string]string, error) {
    resultsSlice, _ := m.ExecSelect()
    retArr := map[string]map[string]string{}
    for _, v := range resultsSlice{
        if v[m.Index] == "" {
            continue
        }
        retArr[v[m.Index]] = v
    }
    m.Clean()
    return retArr, nil
}

// ExecSelect is a method with a sql.
func (m *Model) ExecSelect() ([]map[string]string, error) {
    cond := m.getSQLCond()
    field := m.getSQLField()
    sort := m.getSort()
    limit := m.getSQLLimite()
    sql := "SELECT "+ field +" FROM "+m.Table+cond+sort+limit+";"
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    rows, err := stmt.Query()
    if(err != nil){
        return nil, err
    }
    defer rows.Close()
    fields, err := rows.Columns()
    if(err != nil){
        return nil, err
    }
    var resultsSlice []map[string]string
    for rows.Next(){
        result := make(map[string]string)
        var scanResultContainers []interface{}
        for i := 0; i < len(fields); i++ {
            var scanResultContainer interface{}
			scanResultContainers = append(scanResultContainers, &scanResultContainer)
        }
        if err := rows.Scan(scanResultContainers...); err != nil {
			return nil, err
		}
        for k, v := range fields {
            rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[k]))
            if rawValue.Interface() == nil{
                continue
            }
            rawType := reflect.TypeOf(rawValue.Interface())
			rawVal := reflect.ValueOf(rawValue.Interface())
            var str string
            switch rawType.Kind() {
                case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                    str = strconv.FormatInt(rawVal.Int(), 10)
                    result[v] = str
                case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
                    str = strconv.FormatUint(rawVal.Uint(), 10)
                    result[v] = str
                case reflect.Float32, reflect.Float64:
                    str = strconv.FormatFloat(rawVal.Float(), 'f', -1, 64)
                    result[v] = str
                case reflect.Slice:
                    if rawType.Elem().Kind() == reflect.Uint8 {
                        result[v] = string(rawVal.Interface().([]byte))
                        break
                    }
                case reflect.String:
                    str = rawVal.String()
                    result[v] = str
                case reflect.Struct:
                    str = rawVal.Interface().(time.Time).Format("2006-01-02 15:04:05.000 -0700")
                    result[v] = str
                case reflect.Bool:
                    if rawVal.Bool() {
                        result[v] = "1"
                    } else {
                        result[v] = "0"
                    }
                }
            }
            resultsSlice = append(resultsSlice, result)
        }
        m.Clean()
        return resultsSlice, nil
}

func (m *Model) ExecSelectOne() (map[string]string, error) {
    resultsSlice, err := m.ExecSelect()
    if resultsSlice == nil{
        return resultsSlice, err
    }
    return resultsSlice[0], nil
}

func (m *Model) ExecUpdate() (sql.Result, error){
    updateStr := m.getSQLUpdate()
    condStr := m.getSQLCond()
    sql := "UPDATE "+ m.Table +" SET "+ updateStr + condStr +";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func (m *Model) ExecInsert() (sql.Result, error) {
    insert := m.getSQLInsert()
    sql := "INSERT INTO "+m.Table+" "+insert+";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func (m *Model) ExecReplace() (sql.Result, error) {
    insert := m.getSQLInsert()
    sql := "REPLACE INTO "+m.Table+" "+insert+";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func (m *Model) ExecDelete() (sql.Result, error) {
    condStr := m.getSQLCond()
    sql := "DELETE FROM "+ m.Table + condStr +";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func GetLastInsertId(result sql.Result)(int64, error){
    return result.LastInsertId()
}

func GetRowsAffected(result sql.Result)(int64, error){
    return result.RowsAffected()
}

func (m *Model)getSQLCond() string {
    if str, ok := m.Cond.(string); ok{
        return str
    }
    var strArr []string
    if arr, ok := m.Cond.(map[string]string); ok{
        var strArr []string
        for k, v := range arr{
            strArr = append(strArr, k+"='"+v+"'")
        }
        return " WHERE "+ strings.Join(strArr, " && ")
    }
    if arr, ok := m.Cond.(map[string]interface{}); ok{
        for k, v := range arr{
            if isStr, ok := v.(string); ok{
                strArr = append(strArr, k+"='"+isStr+"'")
            }
            if isStrArr, ok := v.([]string); ok{
                for k, v := range isStrArr{
                    isStrArr[k] = "'"+v+"'"
                }
                strArr = append(strArr, k+" in ("+strings.Join(isStrArr, ",")+")")
            }
        }
        return " WHERE "+ strings.Join(strArr, " && ")
    }
    return ""
}

func (m *Model)getSQLField() string {
    if m.Field != ""{
        return m.Field
    }
    return "*"
}

func (m *Model)getSort() string {
    if m.Sort != ""{
        return " ORDER BY "+m.Sort+" "
    }
    return ""
}

func (m *Model)getSQLUpdate() string {
    var strArr []string
    for k, v := range m.Update{
        strArr = append(strArr, k+"='"+v+"'")
    }
    return strings.Join(strArr, ",")
}

func (m *Model)getSQLInsert() string {
    var fieldArr, valueArr []string
    for k, v := range m.Insert{
        fieldArr = append(fieldArr, k)
        valueArr = append(valueArr, "'"+v+"'")
    }
    return "("+ strings.Join(fieldArr, ",") +") values ("+ strings.Join(valueArr, ",") +")"
}

func (m *Model)getSQLFatch() int {
    if(m.Fetch == 0){
        return 0
    }
    return 1
}

func (m *Model)getSQLLimite() string {
    if strArr, ok := m.Limit.([2]int); ok{
        return " LIMIT "+fmt.Sprintf("%d", strArr[0])+", "+fmt.Sprintf("%d", strArr[1])
    }
    return ""
}

func (m *Model)Clean() {
    m.Cond = nil
    m.Insert = nil
    m.Update = nil
    m.Field = ""
    m.Table = ""
    m.Index = ""
    m.Limit = nil
    m.Sort = ""
    m.Fetch = 0
}<commit_msg>fix bugs<commit_after>package QesyDb

import(
    "database/sql"
    "fmt"
    "strings"
    "log"
    _"github.com/go-sql-driver/mysql"
    "reflect"
    "strconv"
    "time"
)

var Db *sql.DB

type Model struct{
    Cond interface{}
    Insert map[string]string
    Update map[string]string
    Field string
    Table string
    Index string
    Limit interface{}
    Sort string
    Fetch int
}

// Connect  is a method with a sql.
func Connect(connStr string){
    sqlDb, err := sql.Open("mysql", connStr)
    if(err != nil){
        log.Fatal("mysql connect error")
    }
    err = sqlDb.Ping()
    if(err != nil){
        log.Fatal("mysql ping error")
    }
	fmt.Println("mysql connect sueccss")
    Db = sqlDb
}

// ExecSelectIndex  is a method with a sql.
func (m *Model) ExecSelectIndex() (map[string]map[string]string, error) {
    resultsSlice, _ := m.ExecSelect()
    retArr := map[string]map[string]string{}
    for _, v := range resultsSlice{
        if v[m.Index] == "" {
            continue
        }
        retArr[v[m.Index]] = v
    }
    m.Clean()
    return retArr, nil
}

// ExecSelect is a method with a sql.
func (m *Model) ExecSelect() ([]map[string]string, error) {
    cond := m.getSQLCond()
    field := m.getSQLField()
    sort := m.getSort()
    limit := m.getSQLLimite()
    sql := "SELECT "+ field +" FROM "+m.Table+cond+sort+limit+";"
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    rows, err := stmt.Query()
    if(err != nil){
        return nil, err
    }
    defer rows.Close()
    fields, err := rows.Columns()
    if(err != nil){
        return nil, err
    }
    var resultsSlice []map[string]string
    for rows.Next(){
        result := make(map[string]string)
        var scanResultContainers []interface{}
        for i := 0; i < len(fields); i++ {
            var scanResultContainer interface{}
			scanResultContainers = append(scanResultContainers, &scanResultContainer)
        }
        if err := rows.Scan(scanResultContainers...); err != nil {
			return nil, err
		}
        for k, v := range fields {
            rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[k]))
            if rawValue.Interface() == nil{
                continue
            }
            rawType := reflect.TypeOf(rawValue.Interface())
			rawVal := reflect.ValueOf(rawValue.Interface())
            var str string
            switch rawType.Kind() {
                case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                    str = strconv.FormatInt(rawVal.Int(), 10)
                    result[v] = str
                case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
                    str = strconv.FormatUint(rawVal.Uint(), 10)
                    result[v] = str
                case reflect.Float32, reflect.Float64:
                    str = strconv.FormatFloat(rawVal.Float(), 'f', -1, 64)
                    result[v] = str
                case reflect.Slice:
                    if rawType.Elem().Kind() == reflect.Uint8 {
                        result[v] = string(rawVal.Interface().([]byte))
                        break
                    }
                case reflect.String:
                    str = rawVal.String()
                    result[v] = str
                case reflect.Struct:
                    str = rawVal.Interface().(time.Time).Format("2006-01-02 15:04:05.000 -0700")
                    result[v] = str
                case reflect.Bool:
                    if rawVal.Bool() {
                        result[v] = "1"
                    } else {
                        result[v] = "0"
                    }
                }
            }
            resultsSlice = append(resultsSlice, result)
        }
        m.Clean()
        return resultsSlice, nil
}

func (m *Model) ExecSelectOne() (map[string]string, error) {
    resultsSlice, err := m.ExecSelect()
    if resultsSlice == nil{
        return nil, err
    }
    return resultsSlice[0], nil
}

func (m *Model) ExecUpdate() (sql.Result, error){
    updateStr := m.getSQLUpdate()
    condStr := m.getSQLCond()
    sql := "UPDATE "+ m.Table +" SET "+ updateStr + condStr +";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func (m *Model) ExecInsert() (sql.Result, error) {
    insert := m.getSQLInsert()
    sql := "INSERT INTO "+m.Table+" "+insert+";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func (m *Model) ExecReplace() (sql.Result, error) {
    insert := m.getSQLInsert()
    sql := "REPLACE INTO "+m.Table+" "+insert+";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func (m *Model) ExecDelete() (sql.Result, error) {
    condStr := m.getSQLCond()
    sql := "DELETE FROM "+ m.Table + condStr +";";
    stmt, err := Db.Prepare(sql)
    if(err != nil){
        return nil, err
    }
    result, err := stmt.Exec()
    m.Clean()
    return result, err
}

func GetLastInsertId(result sql.Result)(int64, error){
    return result.LastInsertId()
}

func GetRowsAffected(result sql.Result)(int64, error){
    return result.RowsAffected()
}

func (m *Model)getSQLCond() string {
    if str, ok := m.Cond.(string); ok{
        return str
    }
    var strArr []string
    if arr, ok := m.Cond.(map[string]string); ok{
        var strArr []string
        for k, v := range arr{
            strArr = append(strArr, k+"='"+v+"'")
        }
        return " WHERE "+ strings.Join(strArr, " && ")
    }
    if arr, ok := m.Cond.(map[string]interface{}); ok{
        for k, v := range arr{
            if isStr, ok := v.(string); ok{
                strArr = append(strArr, k+"='"+isStr+"'")
            }
            if isStrArr, ok := v.([]string); ok{
                for k, v := range isStrArr{
                    isStrArr[k] = "'"+v+"'"
                }
                strArr = append(strArr, k+" in ("+strings.Join(isStrArr, ",")+")")
            }
        }
        return " WHERE "+ strings.Join(strArr, " && ")
    }
    return ""
}

func (m *Model)getSQLField() string {
    if m.Field != ""{
        return m.Field
    }
    return "*"
}

func (m *Model)getSort() string {
    if m.Sort != ""{
        return " ORDER BY "+m.Sort+" "
    }
    return ""
}

func (m *Model)getSQLUpdate() string {
    var strArr []string
    for k, v := range m.Update{
        strArr = append(strArr, k+"='"+v+"'")
    }
    return strings.Join(strArr, ",")
}

func (m *Model)getSQLInsert() string {
    var fieldArr, valueArr []string
    for k, v := range m.Insert{
        fieldArr = append(fieldArr, k)
        valueArr = append(valueArr, "'"+v+"'")
    }
    return "("+ strings.Join(fieldArr, ",") +") values ("+ strings.Join(valueArr, ",") +")"
}

func (m *Model)getSQLFatch() int {
    if(m.Fetch == 0){
        return 0
    }
    return 1
}

func (m *Model)getSQLLimite() string {
    if strArr, ok := m.Limit.([2]int); ok{
        return " LIMIT "+fmt.Sprintf("%d", strArr[0])+", "+fmt.Sprintf("%d", strArr[1])
    }
    return ""
}

func (m *Model)Clean() {
    m.Cond = nil
    m.Insert = nil
    m.Update = nil
    m.Field = ""
    m.Table = ""
    m.Index = ""
    m.Limit = nil
    m.Sort = ""
    m.Fetch = 0
}<|endoftext|>


<commit_before>package node

import (
	"context"
	"errors"
	"net/http"
	_ "net/http/pprof"
	"os"
	"path/filepath"
	"time"

	"github.com/prometheus/prometheus/util/flock"
	log "github.com/sirupsen/logrus"
	cmn "github.com/tendermint/tmlibs/common"
	dbm "github.com/tendermint/tmlibs/db"
	browser "github.com/toqueteos/webbrowser"

	"github.com/bytom/accesstoken"
	"github.com/bytom/account"
	"github.com/bytom/api"
	"github.com/bytom/asset"
	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/txfeed"
	cfg "github.com/bytom/config"
	"github.com/bytom/consensus"
	"github.com/bytom/database/leveldb"
	"github.com/bytom/env"
	"github.com/bytom/mining/cpuminer"
	"github.com/bytom/mining/miningpool"
	"github.com/bytom/netsync"
	"github.com/bytom/protocol"
	"github.com/bytom/protocol/bc"
	"github.com/bytom/types"
	w "github.com/bytom/wallet"
)

const (
	webAddress               = "http://127.0.0.1:9888"
	expireReservationsPeriod = time.Second
	maxNewBlockChSize        = 1024
)

type Node struct {
	cmn.BaseService

	// config
	config *cfg.Config

	syncManager *netsync.SyncManager

	evsw types.EventSwitch // pub/sub for services
	//bcReactor    *bc.BlockchainReactor
	wallet       *w.Wallet
	accessTokens *accesstoken.CredentialStore
	api          *api.API
	chain        *protocol.Chain
	txfeed       *txfeed.Tracker
	cpuMiner     *cpuminer.CPUMiner
	miningPool   *miningpool.MiningPool
	miningEnable bool
}

func NewNode(config *cfg.Config) *Node {
	ctx := context.Background()
	if err := lockDataDirectory(config); err != nil {
		cmn.Exit("Error: " + err.Error())
	}
	initLogFile(config)
	initActiveNetParams(config)
	// Get store
	coreDB := dbm.NewDB("core", config.DBBackend, config.DBDir())
	store := leveldb.NewStore(coreDB)

	tokenDB := dbm.NewDB("accesstoken", config.DBBackend, config.DBDir())
	accessTokens := accesstoken.NewStore(tokenDB)

	// Make event switch
	eventSwitch := types.NewEventSwitch()
	if _, err := eventSwitch.Start(); err != nil {
		cmn.Exit(cmn.Fmt("Failed to start switch: %v", err))
	}

	txPool := protocol.NewTxPool()
	chain, err := protocol.NewChain(store, txPool)
	if err != nil {
		cmn.Exit(cmn.Fmt("Failed to create chain structure: %v", err))
	}

	var accounts *account.Manager = nil
	var assets *asset.Registry = nil
	var wallet *w.Wallet = nil
	var txFeed *txfeed.Tracker = nil

	txFeedDB := dbm.NewDB("txfeeds", config.DBBackend, config.DBDir())
	txFeed = txfeed.NewTracker(txFeedDB, chain)

	if err = txFeed.Prepare(ctx); err != nil {
		log.WithField("error", err).Error("start txfeed")
		return nil
	}

	hsm, err := pseudohsm.New(config.KeysDir())
	if err != nil {
		cmn.Exit(cmn.Fmt("initialize HSM failed: %v", err))
	}

	if !config.Wallet.Disable {
		walletDB := dbm.NewDB("wallet", config.DBBackend, config.DBDir())
		accounts = account.NewManager(walletDB, chain)
		assets = asset.NewRegistry(walletDB, chain)
		wallet, err = w.NewWallet(walletDB, accounts, assets, hsm, chain)
		if err != nil {
			log.WithField("error", err).Error("init NewWallet")
		}

		// trigger rescan wallet
		if config.Wallet.Rescan {
			wallet.RescanBlocks()
		}

		// Clean up expired UTXO reservations periodically.
		go accounts.ExpireReservations(ctx, expireReservationsPeriod)
	}
	newBlockCh := make(chan *bc.Hash, maxNewBlockChSize)

	syncManager, _ := netsync.NewSyncManager(config, chain, txPool, newBlockCh)

	// get transaction from txPool and send it to syncManager and wallet
	go newPoolTxListener(txPool, syncManager, wallet)

	// run the profile server
	profileHost := config.ProfListenAddress
	if profileHost != "" {
		// Profiling bytomd programs.see (https://blog.golang.org/profiling-go-programs)
		// go tool pprof http://profileHose/debug/pprof/heap
		go func() {
			http.ListenAndServe(profileHost, nil)
		}()
	}

	node := &Node{
		config:       config,
		syncManager:  syncManager,
		evsw:         eventSwitch,
		accessTokens: accessTokens,
		wallet:       wallet,
		chain:        chain,
		txfeed:       txFeed,
		miningEnable: config.Mining,
	}

	node.cpuMiner = cpuminer.NewCPUMiner(chain, accounts, txPool, newBlockCh)
	node.miningPool = miningpool.NewMiningPool(chain, accounts, txPool, newBlockCh)

	node.BaseService = *cmn.NewBaseService(nil, "Node", node)

	return node
}

// newPoolTxListener listener transaction from txPool, and send it to syncManager and wallet
func newPoolTxListener(txPool *protocol.TxPool, syncManager *netsync.SyncManager, wallet *w.Wallet) {
	newTxCh := txPool.GetNewTxCh()
	syncManagerTxCh := syncManager.GetNewTxCh()
	walletTxCh := wallet.GetNewTxCh()
	for {
		newTx := <-newTxCh
		syncManagerTxCh <- newTx
		if wallet != nil {
			walletTxCh <- newTx
		}
	}
}

// Lock data directory after daemonization
func lockDataDirectory(config *cfg.Config) error {
	_, _, err := flock.New(filepath.Join(config.RootDir, "LOCK"))
	if err != nil {
		return errors.New("datadir already used by another process")
	}
	return nil
}

func initActiveNetParams(config *cfg.Config) {
	var exist bool
	consensus.ActiveNetParams, exist = consensus.NetParams[config.ChainID]
	if !exist {
		cmn.Exit(cmn.Fmt("chain_id[%v] don't exist", config.ChainID))
	}
}

func initLogFile(config *cfg.Config) {
	if config.LogFile == "" {
		return
	}
	cmn.EnsureDir(filepath.Dir(config.LogFile), 0700)
	file, err := os.OpenFile(config.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err == nil {
		log.SetOutput(file)
	} else {
		log.WithField("err", err).Info("using default")
	}

}

// Lanch web broser or not
func launchWebBrowser() {
	log.Info("Launching System Browser with :", webAddress)
	if err := browser.Open(webAddress); err != nil {
		log.Error(err.Error())
		return
	}
}

func (n *Node) initAndstartApiServer() {
	n.api = api.NewAPI(n.syncManager, n.wallet, n.txfeed, n.cpuMiner, n.miningPool, n.chain, n.config, n.accessTokens)

	listenAddr := env.String("LISTEN", n.config.ApiAddress)
	env.Parse()
	n.api.StartServer(*listenAddr)
}

func (n *Node) OnStart() error {
	if n.miningEnable {
		n.cpuMiner.Start()
	}
	if !n.config.VaultMode {
		n.syncManager.Start()
	}
	n.initAndstartApiServer()
	if !n.config.Web.Closed {
		launchWebBrowser()
	}

	return nil
}

func (n *Node) OnStop() {
	n.BaseService.OnStop()
	if n.miningEnable {
		n.cpuMiner.Stop()
	}
	if !n.config.VaultMode {
		n.syncManager.Stop()
	}
}

func (n *Node) RunForever() {
	// Sleep forever and then...
	cmn.TrapSignal(func() {
		n.Stop()
	})
}

func (n *Node) EventSwitch() types.EventSwitch {
	return n.evsw
}

func (n *Node) SyncManager() *netsync.SyncManager {
	return n.syncManager
}

func (n *Node) MiningPool() *miningpool.MiningPool {
	return n.miningPool
}
<commit_msg>optimise<commit_after>package node

import (
	"context"
	"errors"
	"net/http"
	_ "net/http/pprof"
	"os"
	"path/filepath"
	"time"

	"github.com/prometheus/prometheus/util/flock"
	log "github.com/sirupsen/logrus"
	cmn "github.com/tendermint/tmlibs/common"
	dbm "github.com/tendermint/tmlibs/db"
	browser "github.com/toqueteos/webbrowser"

	"github.com/bytom/accesstoken"
	"github.com/bytom/account"
	"github.com/bytom/api"
	"github.com/bytom/asset"
	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/txfeed"
	cfg "github.com/bytom/config"
	"github.com/bytom/consensus"
	"github.com/bytom/database/leveldb"
	"github.com/bytom/env"
	"github.com/bytom/mining/cpuminer"
	"github.com/bytom/mining/miningpool"
	"github.com/bytom/netsync"
	"github.com/bytom/protocol"
	"github.com/bytom/protocol/bc"
	"github.com/bytom/protocol/bc/types"
	"github.com/bytom/types"
	w "github.com/bytom/wallet"
)

const (
	webAddress               = "http://127.0.0.1:9888"
	expireReservationsPeriod = time.Second
	maxNewBlockChSize        = 1024
)

type Node struct {
	cmn.BaseService

	// config
	config *cfg.Config

	syncManager *netsync.SyncManager

	evsw types.EventSwitch // pub/sub for services
	//bcReactor    *bc.BlockchainReactor
	wallet       *w.Wallet
	accessTokens *accesstoken.CredentialStore
	api          *api.API
	chain        *protocol.Chain
	txfeed       *txfeed.Tracker
	cpuMiner     *cpuminer.CPUMiner
	miningPool   *miningpool.MiningPool
	miningEnable bool
}

func NewNode(config *cfg.Config) *Node {
	ctx := context.Background()
	if err := lockDataDirectory(config); err != nil {
		cmn.Exit("Error: " + err.Error())
	}
	initLogFile(config)
	initActiveNetParams(config)
	// Get store
	coreDB := dbm.NewDB("core", config.DBBackend, config.DBDir())
	store := leveldb.NewStore(coreDB)

	tokenDB := dbm.NewDB("accesstoken", config.DBBackend, config.DBDir())
	accessTokens := accesstoken.NewStore(tokenDB)

	// Make event switch
	eventSwitch := types.NewEventSwitch()
	if _, err := eventSwitch.Start(); err != nil {
		cmn.Exit(cmn.Fmt("Failed to start switch: %v", err))
	}

	txPool := protocol.NewTxPool()
	chain, err := protocol.NewChain(store, txPool)
	if err != nil {
		cmn.Exit(cmn.Fmt("Failed to create chain structure: %v", err))
	}

	var accounts *account.Manager = nil
	var assets *asset.Registry = nil
	var wallet *w.Wallet = nil
	var txFeed *txfeed.Tracker = nil

	txFeedDB := dbm.NewDB("txfeeds", config.DBBackend, config.DBDir())
	txFeed = txfeed.NewTracker(txFeedDB, chain)

	if err = txFeed.Prepare(ctx); err != nil {
		log.WithField("error", err).Error("start txfeed")
		return nil
	}

	hsm, err := pseudohsm.New(config.KeysDir())
	if err != nil {
		cmn.Exit(cmn.Fmt("initialize HSM failed: %v", err))
	}

	if !config.Wallet.Disable {
		walletDB := dbm.NewDB("wallet", config.DBBackend, config.DBDir())
		accounts = account.NewManager(walletDB, chain)
		assets = asset.NewRegistry(walletDB, chain)
		wallet, err = w.NewWallet(walletDB, accounts, assets, hsm, chain)
		if err != nil {
			log.WithField("error", err).Error("init NewWallet")
		}

		// trigger rescan wallet
		if config.Wallet.Rescan {
			wallet.RescanBlocks()
		}

		// Clean up expired UTXO reservations periodically.
		go accounts.ExpireReservations(ctx, expireReservationsPeriod)
	}
	newBlockCh := make(chan *bc.Hash, maxNewBlockChSize)

	syncManager, _ := netsync.NewSyncManager(config, chain, txPool, newBlockCh)

	// get transaction from txPool and send it to syncManager and wallet
	go newPoolTxListener(txPool, syncManager, wallet)

	// run the profile server
	profileHost := config.ProfListenAddress
	if profileHost != "" {
		// Profiling bytomd programs.see (https://blog.golang.org/profiling-go-programs)
		// go tool pprof http://profileHose/debug/pprof/heap
		go func() {
			http.ListenAndServe(profileHost, nil)
		}()
	}

	node := &Node{
		config:       config,
		syncManager:  syncManager,
		evsw:         eventSwitch,
		accessTokens: accessTokens,
		wallet:       wallet,
		chain:        chain,
		txfeed:       txFeed,
		miningEnable: config.Mining,
	}

	node.cpuMiner = cpuminer.NewCPUMiner(chain, accounts, txPool, newBlockCh)
	node.miningPool = miningpool.NewMiningPool(chain, accounts, txPool, newBlockCh)

	node.BaseService = *cmn.NewBaseService(nil, "Node", node)

	return node
}

// newPoolTxListener listener transaction from txPool, and send it to syncManager and wallet
func newPoolTxListener(txPool *protocol.TxPool, syncManager *netsync.SyncManager, wallet *w.Wallet) {
	newTxCh := txPool.GetNewTxCh()
	syncManagerTxCh := syncManager.GetNewTxCh()

	for {
		newTx := <-newTxCh
		syncManagerTxCh <- newTx
		if wallet != nil {
			wallet.GetNewTxCh() <- newTx
		}
	}
}

// Lock data directory after daemonization
func lockDataDirectory(config *cfg.Config) error {
	_, _, err := flock.New(filepath.Join(config.RootDir, "LOCK"))
	if err != nil {
		return errors.New("datadir already used by another process")
	}
	return nil
}

func initActiveNetParams(config *cfg.Config) {
	var exist bool
	consensus.ActiveNetParams, exist = consensus.NetParams[config.ChainID]
	if !exist {
		cmn.Exit(cmn.Fmt("chain_id[%v] don't exist", config.ChainID))
	}
}

func initLogFile(config *cfg.Config) {
	if config.LogFile == "" {
		return
	}
	cmn.EnsureDir(filepath.Dir(config.LogFile), 0700)
	file, err := os.OpenFile(config.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err == nil {
		log.SetOutput(file)
	} else {
		log.WithField("err", err).Info("using default")
	}

}

// Lanch web broser or not
func launchWebBrowser() {
	log.Info("Launching System Browser with :", webAddress)
	if err := browser.Open(webAddress); err != nil {
		log.Error(err.Error())
		return
	}
}

func (n *Node) initAndstartApiServer() {
	n.api = api.NewAPI(n.syncManager, n.wallet, n.txfeed, n.cpuMiner, n.miningPool, n.chain, n.config, n.accessTokens)

	listenAddr := env.String("LISTEN", n.config.ApiAddress)
	env.Parse()
	n.api.StartServer(*listenAddr)
}

func (n *Node) OnStart() error {
	if n.miningEnable {
		n.cpuMiner.Start()
	}
	if !n.config.VaultMode {
		n.syncManager.Start()
	}
	n.initAndstartApiServer()
	if !n.config.Web.Closed {
		launchWebBrowser()
	}

	return nil
}

func (n *Node) OnStop() {
	n.BaseService.OnStop()
	if n.miningEnable {
		n.cpuMiner.Stop()
	}
	if !n.config.VaultMode {
		n.syncManager.Stop()
	}
}

func (n *Node) RunForever() {
	// Sleep forever and then...
	cmn.TrapSignal(func() {
		n.Stop()
	})
}

func (n *Node) EventSwitch() types.EventSwitch {
	return n.evsw
}

func (n *Node) SyncManager() *netsync.SyncManager {
	return n.syncManager
}

func (n *Node) MiningPool() *miningpool.MiningPool {
	return n.miningPool
}
<|endoftext|>


<commit_before>package node

import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"io"
	"log"
	"os"
)

const blockSize = 4096 // Guestimate of a FS block-size for optimal read call

// Node type
type Node struct {
	Path string // File path
	Size int64  // File size
	Hash string // String form of SHA1 hash
}

func (n *Node) Value() interface{} {
	return n
}

// Calculate hash
func (n *Node) CalculateHash(fast bool) error {
	readSize := n.Size // by default, read the entire file

	if fast {
		if n.Size > blockSize {
			readSize = blockSize // Limit number of read bytes to BlockSize on fast pass
		} else {
			// Skip small file on a "fast" pass
			return nil
		}
	}

	// Open file
	file, err := os.Open(n.Path)
	if err != nil {
		log.Println("WARN", err)
		return err
	}
	// Never forget to close it
	defer file.Close()

	var nbytes int64 // bytes read
	hash := sha1.New()

	// Always read no more that the file size already determined
	nbytes, err = io.CopyN(hash, file, readSize) // Use io.CopyN() for optimal filesystem and memory use
	if err != nil {
		log.Println("WARN", err)
		return err
	}

	// Paranoid sanity check
	if nbytes != readSize {
		err = errors.New("Partial read: " + n.Path)
		log.Println("WARN", err)
		return err
	}

	// Add hash value
	n.Hash = hex.EncodeToString(hash.Sum(nil))
	return nil
}
<commit_msg>Use 16KB for read size<commit_after>package node

import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"io"
	"log"
	"os"
)

const blockSize = 4096 * 4 // Guestimate of a FS block-size for optimal read call

// Node type
type Node struct {
	Path string // File path
	Size int64  // File size
	Hash string // String form of SHA1 hash
}

func (n *Node) Value() interface{} {
	return n
}

// Calculate hash
func (n *Node) CalculateHash(fast bool) error {
	readSize := n.Size // by default, read the entire file

	if fast {
		if n.Size > blockSize {
			readSize = blockSize // Limit number of read bytes to BlockSize on fast pass
		} else {
			// Skip small file on a "fast" pass
			return nil
		}
	}

	// Open file
	file, err := os.Open(n.Path)
	if err != nil {
		log.Println("WARN", err)
		return err
	}
	// Never forget to close it
	defer file.Close()

	var nbytes int64 // bytes read
	hash := sha1.New()

	// Always read no more that the file size already determined
	nbytes, err = io.CopyN(hash, file, readSize) // Use io.CopyN() for optimal filesystem and memory use
	if err != nil {
		log.Println("WARN", err)
		return err
	}

	// Paranoid sanity check
	if nbytes != readSize {
		err = errors.New("Partial read: " + n.Path)
		log.Println("WARN", err)
		return err
	}

	// Add hash value
	n.Hash = hex.EncodeToString(hash.Sum(nil))
	return nil
}
<|endoftext|>


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

package service

import (
	"testing"
)

func TestNodeInfoName(t *testing.T) {
	tests := []struct{ path, name string }{
		{"", ""},
		{"/", ""},
		{"/foo", "foo"},
		{"/foo/", "foo"},
		{"/foo/bar", "bar"},
		{"/foo/bar/", "bar"},
	}
	for _, test := range tests {
		node := NodeInfo{Path: test.path}
		name := node.Name()
		if name != test.name {
			t.Errorf(`%v.Name() = %q, should be %q`, node, name, test.name)
		}
	}
}
<commit_msg>Fix node test.<commit_after>// Copyright 2012-2013 Christian Neumann
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"testing"
)

func TestNodeFieldsName(t *testing.T) {
	tests := []struct{ path, name string }{
		{"", ""},
		{"/", ""},
		{"/foo", "foo"},
		{"/foo/", "foo"},
		{"/foo/bar", "bar"},
		{"/foo/bar/", "bar"},
	}
	for _, test := range tests {
		node := NodeFields{Path: test.path}
		name := node.Name()
		if name != test.name {
			t.Errorf(`%v.Name() = %q, should be %q`, node, name, test.name)
		}
	}
}
<|endoftext|>


<commit_before>package machine

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestMachineNewName(t *testing.T) {
	a := newMachineName("machine-template-%s")
	b := newMachineName("machine-template-%s")
	assert.NotEqual(t, a, b)
}
<commit_msg>Test filter<commit_after>package machine

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestMachineNewName(t *testing.T) {
	a := newMachineName("machine-template-%s")
	b := newMachineName("machine-template-%s")
	assert.NotEqual(t, a, b)
}

func TestMachineFilter(t *testing.T) {
	filter := "machine-template-%s"
	machines := []string{
		"test-machine",
		"machine-template-10",
	}
	filtered := filterMachineList(machines, filter)

	assert.NotContains(t, filtered, machines[0])
	assert.Contains(t, filtered, machines[1])
}
<|endoftext|>


<commit_before>// Copyright 2016 tsuru 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 rebuild

import (
	"net/url"
	"strings"

	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/router"
	appTypes "github.com/tsuru/tsuru/types/app"
)

type RebuildRoutesResult struct {
	Added   []string
	Removed []string
}

type RebuildApp interface {
	router.App
	GetCname() []string
	GetRouters() []appTypes.AppRouter
	GetHealthcheckData() (router.HealthcheckData, error)
	RoutableAddresses() ([]url.URL, error)
	InternalLock(string) (bool, error)
	Unlock()
}

func RebuildRoutes(app RebuildApp, dry bool) (map[string]RebuildRoutesResult, error) {
	result := make(map[string]RebuildRoutesResult)
	for _, appRouter := range app.GetRouters() {
		resultInRouter, err := rebuildRoutesInRouter(app, dry, appRouter)
		if err != nil {
			return nil, err
		}
		result[appRouter.Name] = *resultInRouter
	}
	return result, nil
}

func rebuildRoutesInRouter(app RebuildApp, dry bool, appRouter appTypes.AppRouter) (*RebuildRoutesResult, error) {
	log.Debugf("[rebuild-routes] rebuilding routes for app %q", app.GetName())
	r, err := router.Get(appRouter.Name)
	if err != nil {
		return nil, err
	}
	if optsRouter, ok := r.(router.OptsRouter); ok {
		err = optsRouter.AddBackendOpts(app, appRouter.Opts)
	} else {
		err = r.AddBackend(app)
	}
	if err != nil && err != router.ErrBackendExists {
		return nil, err
	}
	if cnameRouter, ok := r.(router.CNameRouter); ok {
		for _, cname := range app.GetCname() {
			err = cnameRouter.SetCName(cname, app.GetName())
			if err != nil && err != router.ErrCNameExists {
				return nil, err
			}
		}
	}
	if hcRouter, ok := r.(router.CustomHealthcheckRouter); ok {
		hcData, err := app.GetHealthcheckData()
		if err != nil {
			return nil, err
		}
		err = hcRouter.SetHealthcheck(app.GetName(), hcData)
		if err != nil {
			return nil, err
		}
	}
	oldRoutes, err := r.Routes(app.GetName())
	if err != nil {
		return nil, err
	}
	log.Debugf("[rebuild-routes] old routes for app %q: %v", app.GetName(), oldRoutes)
	expectedMap := make(map[string]*url.URL)
	addresses, err := app.RoutableAddresses()
	if err != nil {
		return nil, err
	}
	log.Debugf("[rebuild-routes] addresses for app %q: %v", app.GetName(), addresses)
	for i, addr := range addresses {
		expectedMap[addr.Host] = &addresses[i]
	}
	var toRemove []*url.URL
	for _, url := range oldRoutes {
		if _, isPresent := expectedMap[url.Host]; isPresent {
			delete(expectedMap, url.Host)
		} else {
			toRemove = append(toRemove, url)
		}
	}
	var result RebuildRoutesResult
	var toAdd []*url.URL
	for _, toAddURL := range expectedMap {
		toAdd = append(toAdd, toAddURL)
		result.Added = append(result.Added, toAddURL.String())
	}
	for _, toRemoveURL := range toRemove {
		result.Removed = append(result.Removed, toRemoveURL.String())
	}
	if dry {
		log.Debugf("[rebuild-routes] nothing to do. DRY mode for app: %q", app.GetName())
		return &result, nil
	}
	err = r.AddRoutes(app.GetName(), toAdd)
	if err != nil {
		return nil, err
	}
	err = r.RemoveRoutes(app.GetName(), toRemove)
	if err != nil {
		return nil, err
	}
	log.Debugf("[rebuild-routes] routes added for app %q: %s", app.GetName(), strings.Join(result.Added, ", "))
	log.Debugf("[rebuild-routes] routes removed for app %q: %s", app.GetName(), strings.Join(result.Removed, ", "))
	return &result, nil
}
<commit_msg>router/rebuild: fix variable shadowing<commit_after>// Copyright 2016 tsuru 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 rebuild

import (
	"net/url"
	"strings"

	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/router"
	appTypes "github.com/tsuru/tsuru/types/app"
)

type RebuildRoutesResult struct {
	Added   []string
	Removed []string
}

type RebuildApp interface {
	router.App
	GetCname() []string
	GetRouters() []appTypes.AppRouter
	GetHealthcheckData() (router.HealthcheckData, error)
	RoutableAddresses() ([]url.URL, error)
	InternalLock(string) (bool, error)
	Unlock()
}

func RebuildRoutes(app RebuildApp, dry bool) (map[string]RebuildRoutesResult, error) {
	result := make(map[string]RebuildRoutesResult)
	for _, appRouter := range app.GetRouters() {
		resultInRouter, err := rebuildRoutesInRouter(app, dry, appRouter)
		if err != nil {
			return nil, err
		}
		result[appRouter.Name] = *resultInRouter
	}
	return result, nil
}

func rebuildRoutesInRouter(app RebuildApp, dry bool, appRouter appTypes.AppRouter) (*RebuildRoutesResult, error) {
	log.Debugf("[rebuild-routes] rebuilding routes for app %q", app.GetName())
	r, err := router.Get(appRouter.Name)
	if err != nil {
		return nil, err
	}
	if optsRouter, ok := r.(router.OptsRouter); ok {
		err = optsRouter.AddBackendOpts(app, appRouter.Opts)
	} else {
		err = r.AddBackend(app)
	}
	if err != nil && err != router.ErrBackendExists {
		return nil, err
	}
	if cnameRouter, ok := r.(router.CNameRouter); ok {
		for _, cname := range app.GetCname() {
			err = cnameRouter.SetCName(cname, app.GetName())
			if err != nil && err != router.ErrCNameExists {
				return nil, err
			}
		}
	}
	if hcRouter, ok := r.(router.CustomHealthcheckRouter); ok {
		hcData, errHc := app.GetHealthcheckData()
		if errHc != nil {
			return nil, errHc
		}
		errHc = hcRouter.SetHealthcheck(app.GetName(), hcData)
		if errHc != nil {
			return nil, errHc
		}
	}
	oldRoutes, err := r.Routes(app.GetName())
	if err != nil {
		return nil, err
	}
	log.Debugf("[rebuild-routes] old routes for app %q: %v", app.GetName(), oldRoutes)
	expectedMap := make(map[string]*url.URL)
	addresses, err := app.RoutableAddresses()
	if err != nil {
		return nil, err
	}
	log.Debugf("[rebuild-routes] addresses for app %q: %v", app.GetName(), addresses)
	for i, addr := range addresses {
		expectedMap[addr.Host] = &addresses[i]
	}
	var toRemove []*url.URL
	for _, url := range oldRoutes {
		if _, isPresent := expectedMap[url.Host]; isPresent {
			delete(expectedMap, url.Host)
		} else {
			toRemove = append(toRemove, url)
		}
	}
	var result RebuildRoutesResult
	var toAdd []*url.URL
	for _, toAddURL := range expectedMap {
		toAdd = append(toAdd, toAddURL)
		result.Added = append(result.Added, toAddURL.String())
	}
	for _, toRemoveURL := range toRemove {
		result.Removed = append(result.Removed, toRemoveURL.String())
	}
	if dry {
		log.Debugf("[rebuild-routes] nothing to do. DRY mode for app: %q", app.GetName())
		return &result, nil
	}
	err = r.AddRoutes(app.GetName(), toAdd)
	if err != nil {
		return nil, err
	}
	err = r.RemoveRoutes(app.GetName(), toRemove)
	if err != nil {
		return nil, err
	}
	log.Debugf("[rebuild-routes] routes added for app %q: %s", app.GetName(), strings.Join(result.Added, ", "))
	log.Debugf("[rebuild-routes] routes removed for app %q: %s", app.GetName(), strings.Join(result.Removed, ", "))
	return &result, nil
}
<|endoftext|>


<commit_before>package service

import (
	"io"
	"sync"
	"time"

	"github.com/micro/go-micro/router"
	pb "github.com/micro/go-micro/router/service/proto"
)

type watcher struct {
	sync.RWMutex
	opts    router.WatchOptions
	resChan chan *router.Event
	done    chan struct{}
}

func newWatcher(rsp pb.Router_WatchService, opts router.WatchOptions) (*watcher, error) {
	w := &watcher{
		opts:    opts,
		resChan: make(chan *router.Event),
		done:    make(chan struct{}),
	}

	go func() {
		for {
			select {
			case <-w.done:
				return
			default:
				if err := w.watch(rsp); err != nil {
					w.Stop()
					return
				}
			}
		}
	}()

	return w, nil
}

// watchRouter watches router and send events to all registered watchers
func (w *watcher) watch(stream pb.Router_WatchService) error {
	defer stream.Close()

	var watchErr error

	for {
		resp, err := stream.Recv()
		if err != nil {
			if err != io.EOF {
				watchErr = err
			}
			break
		}

		route := router.Route{
			Service: resp.Route.Service,
			Address: resp.Route.Address,
			Gateway: resp.Route.Gateway,
			Network: resp.Route.Network,
			Link:    resp.Route.Link,
			Metric:  resp.Route.Metric,
		}

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

		select {
		case w.resChan <- event:
		case <-w.done:
		}
	}

	return watchErr
}

// Next is a blocking call that returns watch result
func (w *watcher) Next() (*router.Event, error) {
	for {
		select {
		case res := <-w.resChan:
			switch w.opts.Service {
			case res.Route.Service, "*":
				return res, nil
			default:
				continue
			}
		case <-w.done:
			return nil, router.ErrWatcherStopped
		}
	}
}

// Chan returns event channel
func (w *watcher) Chan() (<-chan *router.Event, error) {
	return w.resChan, nil
}

// Stop stops watcher
func (w *watcher) Stop() {
	w.Lock()
	defer w.Unlock()

	select {
	case <-w.done:
		return
	default:
		close(w.done)
	}
}
<commit_msg>close stream<commit_after>package service

import (
	"io"
	"sync"
	"time"

	"github.com/micro/go-micro/router"
	pb "github.com/micro/go-micro/router/service/proto"
)

type watcher struct {
	sync.RWMutex
	opts    router.WatchOptions
	resChan chan *router.Event
	done    chan struct{}
}

func newWatcher(rsp pb.Router_WatchService, opts router.WatchOptions) (*watcher, error) {
	w := &watcher{
		opts:    opts,
		resChan: make(chan *router.Event),
		done:    make(chan struct{}),
	}

	go func() {
		for {
			select {
			case <-w.done:
				return
			default:
				if err := w.watch(rsp); err != nil {
					w.Stop()
					return
				}
			}
		}
	}()

	return w, nil
}

// watchRouter watches router and send events to all registered watchers
func (w *watcher) watch(stream pb.Router_WatchService) error {
	var watchErr error

	for {
		resp, err := stream.Recv()
		if err != nil {
			if err != io.EOF {
				watchErr = err
			}
			break
		}

		route := router.Route{
			Service: resp.Route.Service,
			Address: resp.Route.Address,
			Gateway: resp.Route.Gateway,
			Network: resp.Route.Network,
			Link:    resp.Route.Link,
			Metric:  resp.Route.Metric,
		}

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

		select {
		case w.resChan <- event:
		case <-w.done:
		}
	}

	return watchErr
}

// Next is a blocking call that returns watch result
func (w *watcher) Next() (*router.Event, error) {
	for {
		select {
		case res := <-w.resChan:
			switch w.opts.Service {
			case res.Route.Service, "*":
				return res, nil
			default:
				continue
			}
		case <-w.done:
			return nil, router.ErrWatcherStopped
		}
	}
}

// Chan returns event channel
func (w *watcher) Chan() (<-chan *router.Event, error) {
	return w.resChan, nil
}

// Stop stops watcher
func (w *watcher) Stop() {
	w.Lock()
	defer w.Unlock()

	select {
	case <-w.done:
		return
	default:
		w.stream.Close()
		close(w.done)
	}
}
<|endoftext|>


<commit_before>package edit

// Command history subsystem.

type historyState struct {
	current int
	prefix  string
	line    string
}

func (h *historyState) jump(i int, line string) {
	h.current = i
	h.line = line
}

func (ed *Editor) appendHistory(line string) {
	if ed.store != nil {
		ed.store.AddCmd(line)
		// TODO(xiaq): Report possible error
	}
}

func (ed *Editor) prevHistory() bool {
	if ed.store != nil {
		i, line, err := ed.store.LastCmd(ed.history.current, ed.history.prefix, true)
		if err == nil {
			ed.history.jump(i, line)
			return true
		}
		// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
	}
	return false
}

func (ed *Editor) nextHistory() bool {
	if ed.store != nil {
		// Persistent history
		i, line, err := ed.store.FirstCmd(ed.history.current, ed.history.prefix, true)
		if err == nil {
			ed.history.jump(i, line)
			return true
		}
		// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
	}

	return false
}

// acceptHistory accepts the currently selected history.
func (ed *Editor) acceptHistory() {
	ed.line = ed.history.line
	ed.dot = len(ed.line)
}
<commit_msg>Fix select-history-next.<commit_after>package edit

// Command history subsystem.

type historyState struct {
	current int
	prefix  string
	line    string
}

func (h *historyState) jump(i int, line string) {
	h.current = i
	h.line = line
}

func (ed *Editor) appendHistory(line string) {
	if ed.store != nil {
		ed.store.AddCmd(line)
		// TODO(xiaq): Report possible error
	}
}

func (ed *Editor) prevHistory() bool {
	if ed.store != nil {
		i, line, err := ed.store.LastCmd(ed.history.current, ed.history.prefix, true)
		if err == nil {
			ed.history.jump(i, line)
			return true
		}
		// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
	}
	return false
}

func (ed *Editor) nextHistory() bool {
	if ed.store != nil {
		// Persistent history
		i, line, err := ed.store.FirstCmd(ed.history.current+1, ed.history.prefix, true)
		if err == nil {
			ed.history.jump(i, line)
			return true
		}
		// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
	}

	return false
}

// acceptHistory accepts the currently selected history.
func (ed *Editor) acceptHistory() {
	ed.line = ed.history.line
	ed.dot = len(ed.line)
}
<|endoftext|>