<commit_before>package mpredis

import (
	"flag"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/fzzy/radix/redis"
	mp "github.com/mackerelio/go-mackerel-plugin-helper"
	"github.com/mackerelio/golib/logging"
)

var logger = logging.GetLogger("metrics.plugin.redis")

// RedisPlugin mackerel plugin for Redis
type RedisPlugin struct {
	Host          string
	Port          string
	Password      string
	Socket        string
	Prefix        string
	Timeout       int
	Tempfile      string
	ConfigCommand string
}

func authenticateByPassword(c *redis.Client, password string) error {
	if r := c.Cmd("AUTH", password); r.Err != nil {
		logger.Errorf("Failed to authenticate. %s", r.Err)
		return r.Err
	}
	return nil
}

func (m RedisPlugin) fetchPercentageOfMemory(c *redis.Client, stat map[string]interface{}) error {
	r := c.Cmd(m.ConfigCommand, "GET", "maxmemory")
	if r.Err != nil {
		logger.Errorf("Failed to run `%s GET maxmemory` command. %s", m.ConfigCommand, r.Err)
		return r.Err
	}

	res, err := r.Hash()
	if err != nil {
		logger.Errorf("Failed to fetch maxmemory. %s", err)
		return err
	}

	maxsize, err := strconv.ParseFloat(res["maxmemory"], 64)
	if err != nil {
		logger.Errorf("Failed to parse maxmemory. %s", err)
		return err
	}

	if maxsize == 0.0 {
		stat["percentage_of_memory"] = 0.0
	} else {
		stat["percentage_of_memory"] = 100.0 * stat["used_memory"].(float64) / maxsize
	}

	return nil
}

func (m RedisPlugin) fetchPercentageOfClients(c *redis.Client, stat map[string]interface{}) error {
	r := c.Cmd(m.ConfigCommand, "GET", "maxclients")
	if r.Err != nil {
		logger.Errorf("Failed to run `%s GET maxclients` command. %s", m.ConfigCommand, r.Err)
		return r.Err
	}

	res, err := r.Hash()
	if err != nil {
		logger.Errorf("Failed to fetch maxclients. %s", err)
		return err
	}

	maxsize, err := strconv.ParseFloat(res["maxclients"], 64)
	if err != nil {
		logger.Errorf("Failed to parse maxclients. %s", err)
		return err
	}

	stat["percentage_of_clients"] = 100.0 * stat["connected_clients"].(float64) / maxsize

	return nil
}

func (m RedisPlugin) calculateCapacity(c *redis.Client, stat map[string]interface{}) error {
	if err := m.fetchPercentageOfMemory(c, stat); err != nil {
		return err
	}
	return m.fetchPercentageOfClients(c, stat)
}

// MetricKeyPrefix interface for PluginWithPrefix
func (m RedisPlugin) MetricKeyPrefix() string {
	if m.Prefix == "" {
		m.Prefix = "redis"
	}
	return m.Prefix
}

// FetchMetrics interface for mackerelplugin
func (m RedisPlugin) FetchMetrics() (map[string]interface{}, error) {
	network := "tcp"
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	if m.Socket != "" {
		target = m.Socket
		network = "unix"
	}
	c, err := redis.DialTimeout(network, target, time.Duration(m.Timeout)*time.Second)
	if err != nil {
		logger.Errorf("Failed to connect redis. %s", err)
		return nil, err
	}
	defer c.Close()

	if m.Password != "" {
		if err = authenticateByPassword(c, m.Password); err != nil {
			return nil, err
		}
	}

	r := c.Cmd("info")
	if r.Err != nil {
		logger.Errorf("Failed to run info command. %s", r.Err)
		return nil, r.Err
	}
	str, err := r.Str()
	if err != nil {
		logger.Errorf("Failed to fetch information. %s", err)
		return nil, err
	}

	stat := make(map[string]interface{})

	keysStat := 0.0
	expiresStat := 0.0
	var slaves []string

	for _, line := range strings.Split(str, "\r\n") {
		if line == "" {
			continue
		}
		if re, _ := regexp.MatchString("^#", line); re {
			continue
		}

		record := strings.SplitN(line, ":", 2)
		if len(record) < 2 {
			continue
		}
		key, value := record[0], record[1]

		if re, _ := regexp.MatchString("^slave\\d+", key); re {
			slaves = append(slaves, key)
			kv := strings.Split(value, ",")
			var offset, lag string
			if len(kv) == 5 {
				_, _, _, offset, lag = kv[0], kv[1], kv[2], kv[3], kv[4]
				lagKv := strings.SplitN(lag, "=", 2)
				lagFv, err := strconv.ParseFloat(lagKv[1], 64)
				if err != nil {
					logger.Warningf("Failed to parse slaves. %s", err)
				}
				stat[fmt.Sprintf("%s_lag", key)] = lagFv
			} else {
				_, _, _, offset = kv[0], kv[1], kv[2], kv[3]
			}
			offsetKv := strings.SplitN(offset, "=", 2)
			offsetFv, err := strconv.ParseFloat(offsetKv[1], 64)
			if err != nil {
				logger.Warningf("Failed to parse slaves. %s", err)
			}
			stat[fmt.Sprintf("%s_offset_delay", key)] = offsetFv
			continue
		}

		if re, _ := regexp.MatchString("^db", key); re {
			kv := strings.SplitN(value, ",", 3)
			keys, expires := kv[0], kv[1]

			keysKv := strings.SplitN(keys, "=", 2)
			keysFv, err := strconv.ParseFloat(keysKv[1], 64)
			if err != nil {
				logger.Warningf("Failed to parse db keys. %s", err)
			}
			keysStat += keysFv

			expiresKv := strings.SplitN(expires, "=", 2)
			expiresFv, err := strconv.ParseFloat(expiresKv[1], 64)
			if err != nil {
				logger.Warningf("Failed to parse db expires. %s", err)
			}
			expiresStat += expiresFv

			continue
		}

		stat[key], err = strconv.ParseFloat(value, 64)
		if err != nil {
			continue
		}
	}

	stat["keys"] = keysStat
	stat["expires"] = expiresStat

	if _, ok := stat["keys"]; !ok {
		stat["keys"] = 0
	}
	if _, ok := stat["expires"]; !ok {
		stat["expires"] = 0
	}

	if _, ok := stat["expired_keys"]; ok {
		stat["expired"] = stat["expired_keys"]
	} else {
		stat["expired"] = 0.0
	}

	if m.ConfigCommand != "" {
		if err := m.calculateCapacity(c, stat); err != nil {
			logger.Infof("Failed to calculate capacity. (The cause may be that AWS Elasticache Redis has no `%s` command.) Skip these metrics. %s", m.ConfigCommand, err)
		}
	}

	for _, slave := range slaves {
		stat[fmt.Sprintf("%s_offset_delay", slave)] = stat["master_repl_offset"].(float64) - stat[fmt.Sprintf("%s_offset_delay", slave)].(float64)
	}

	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (m RedisPlugin) GraphDefinition() map[string]mp.Graphs {
	labelPrefix := strings.Title(m.Prefix)

	var graphdef = map[string]mp.Graphs{
		"queries": {
			Label: (labelPrefix + " Queries"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "total_commands_processed", Label: "Queries", Diff: true},
			},
		},
		"connections": {
			Label: (labelPrefix + " Connections"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "total_connections_received", Label: "Connections", Diff: true, Stacked: true},
				{Name: "rejected_connections", Label: "Rejected Connections", Diff: true, Stacked: true},
			},
		},
		"clients": {
			Label: (labelPrefix + " Clients"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "connected_clients", Label: "Connected Clients", Diff: false, Stacked: true},
				{Name: "blocked_clients", Label: "Blocked Clients", Diff: false, Stacked: true},
				{Name: "connected_slaves", Label: "Connected Slaves", Diff: false, Stacked: true},
			},
		},
		"keys": {
			Label: (labelPrefix + " Keys"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "keys", Label: "Keys", Diff: false},
				{Name: "expires", Label: "Keys with expiration", Diff: false},
				{Name: "expired", Label: "Expired Keys", Diff: true},
			},
		},
		"keyspace": {
			Label: (labelPrefix + " Keyspace"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "keyspace_hits", Label: "Keyspace Hits", Diff: true},
				{Name: "keyspace_misses", Label: "Keyspace Missed", Diff: true},
			},
		},
		"memory": {
			Label: (labelPrefix + " Memory"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "used_memory", Label: "Used Memory", Diff: false},
				{Name: "used_memory_rss", Label: "Used Memory RSS", Diff: false},
				{Name: "used_memory_peak", Label: "Used Memory Peak", Diff: false},
				{Name: "used_memory_lua", Label: "Used Memory Lua engine", Diff: false},
			},
		},
		"capacity": {
			Label: (labelPrefix + " Capacity"),
			Unit:  "percentage",
			Metrics: []mp.Metrics{
				{Name: "percentage_of_memory", Label: "Percentage of memory", Diff: false},
				{Name: "percentage_of_clients", Label: "Percentage of clients", Diff: false},
			},
		},
	}

	network := "tcp"
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	if m.Socket != "" {
		target = m.Socket
		network = "unix"
	}

	c, err := redis.DialTimeout(network, target, time.Duration(m.Timeout)*time.Second)
	if err != nil {
		logger.Errorf("Failed to connect redis. %s", err)
		return nil
	}
	defer c.Close()

	if m.Password != "" {
		if err = authenticateByPassword(c, m.Password); err != nil {
			return nil
		}
	}

	r := c.Cmd("info")
	if r.Err != nil {
		logger.Errorf("Failed to run info command. %s", r.Err)
		return nil
	}
	str, err := r.Str()
	if err != nil {
		logger.Errorf("Failed to fetch information. %s", err)
		return nil
	}

	var metricsLag []mp.Metrics
	var metricsOffsetDelay []mp.Metrics
	for _, line := range strings.Split(str, "\r\n") {
		if line == "" {
			continue
		}

		record := strings.SplitN(line, ":", 2)
		if len(record) < 2 {
			continue
		}
		key, _ := record[0], record[1]

		if re, _ := regexp.MatchString("^slave\\d+", key); re {
			metricsLag = append(metricsLag, mp.Metrics{Name: fmt.Sprintf("%s_lag", key), Label: fmt.Sprintf("Replication lag to %s", key), Diff: false})
			metricsOffsetDelay = append(metricsOffsetDelay, mp.Metrics{Name: fmt.Sprintf("%s_offset_delay", key), Label: fmt.Sprintf("Offset delay to %s", key), Diff: false})
		}
	}

	if len(metricsLag) > 0 {
		graphdef["lag"] = mp.Graphs{
			Label:   (labelPrefix + " Slave Lag"),
			Unit:    "seconds",
			Metrics: metricsLag,
		}
	}
	if len(metricsOffsetDelay) > 0 {
		graphdef["offset_delay"] = mp.Graphs{
			Label:   (labelPrefix + " Slave Offset Delay"),
			Unit:    "count",
			Metrics: metricsOffsetDelay,
		}
	}

	return graphdef
}

// Do the plugin
func Do() {
	optHost := flag.String("host", "localhost", "Hostname")
	optPort := flag.String("port", "6379", "Port")
	optPassword := flag.String("password", os.Getenv("REDIS_PASSWORD"), "Password")
	optSocket := flag.String("socket", "", "Server socket (overrides host and port)")
	optPrefix := flag.String("metric-key-prefix", "redis", "Metric key prefix")
	optTimeout := flag.Int("timeout", 5, "Timeout")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	optConfigCommand := flag.String("config-command", "CONFIG", "Custom CONFIG command. Disable CONFIG command when passed \"\".")

	flag.Parse()

	redis := RedisPlugin{
		Timeout:       *optTimeout,
		Prefix:        *optPrefix,
		ConfigCommand: *optConfigCommand,
	}
	if *optSocket != "" {
		redis.Socket = *optSocket
	} else {
		redis.Host = *optHost
		redis.Port = *optPort
		redis.Password = *optPassword
	}
	helper := mp.NewMackerelPlugin(redis)
	helper.Tempfile = *optTempfile

	helper.Run()
}
<commit_msg>redis plugin send Uptime<commit_after>package mpredis

import (
	"flag"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/fzzy/radix/redis"
	mp "github.com/mackerelio/go-mackerel-plugin-helper"
	"github.com/mackerelio/golib/logging"
)

var logger = logging.GetLogger("metrics.plugin.redis")

// RedisPlugin mackerel plugin for Redis
type RedisPlugin struct {
	Host          string
	Port          string
	Password      string
	Socket        string
	Prefix        string
	Timeout       int
	Tempfile      string
	ConfigCommand string
}

func authenticateByPassword(c *redis.Client, password string) error {
	if r := c.Cmd("AUTH", password); r.Err != nil {
		logger.Errorf("Failed to authenticate. %s", r.Err)
		return r.Err
	}
	return nil
}

func (m RedisPlugin) fetchPercentageOfMemory(c *redis.Client, stat map[string]interface{}) error {
	r := c.Cmd(m.ConfigCommand, "GET", "maxmemory")
	if r.Err != nil {
		logger.Errorf("Failed to run `%s GET maxmemory` command. %s", m.ConfigCommand, r.Err)
		return r.Err
	}

	res, err := r.Hash()
	if err != nil {
		logger.Errorf("Failed to fetch maxmemory. %s", err)
		return err
	}

	maxsize, err := strconv.ParseFloat(res["maxmemory"], 64)
	if err != nil {
		logger.Errorf("Failed to parse maxmemory. %s", err)
		return err
	}

	if maxsize == 0.0 {
		stat["percentage_of_memory"] = 0.0
	} else {
		stat["percentage_of_memory"] = 100.0 * stat["used_memory"].(float64) / maxsize
	}

	return nil
}

func (m RedisPlugin) fetchPercentageOfClients(c *redis.Client, stat map[string]interface{}) error {
	r := c.Cmd(m.ConfigCommand, "GET", "maxclients")
	if r.Err != nil {
		logger.Errorf("Failed to run `%s GET maxclients` command. %s", m.ConfigCommand, r.Err)
		return r.Err
	}

	res, err := r.Hash()
	if err != nil {
		logger.Errorf("Failed to fetch maxclients. %s", err)
		return err
	}

	maxsize, err := strconv.ParseFloat(res["maxclients"], 64)
	if err != nil {
		logger.Errorf("Failed to parse maxclients. %s", err)
		return err
	}

	stat["percentage_of_clients"] = 100.0 * stat["connected_clients"].(float64) / maxsize

	return nil
}

func (m RedisPlugin) calculateCapacity(c *redis.Client, stat map[string]interface{}) error {
	if err := m.fetchPercentageOfMemory(c, stat); err != nil {
		return err
	}
	return m.fetchPercentageOfClients(c, stat)
}

// MetricKeyPrefix interface for PluginWithPrefix
func (m RedisPlugin) MetricKeyPrefix() string {
	if m.Prefix == "" {
		m.Prefix = "redis"
	}
	return m.Prefix
}

// FetchMetrics interface for mackerelplugin
func (m RedisPlugin) FetchMetrics() (map[string]interface{}, error) {
	network := "tcp"
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	if m.Socket != "" {
		target = m.Socket
		network = "unix"
	}
	c, err := redis.DialTimeout(network, target, time.Duration(m.Timeout)*time.Second)
	if err != nil {
		logger.Errorf("Failed to connect redis. %s", err)
		return nil, err
	}
	defer c.Close()

	if m.Password != "" {
		if err = authenticateByPassword(c, m.Password); err != nil {
			return nil, err
		}
	}

	r := c.Cmd("info")
	if r.Err != nil {
		logger.Errorf("Failed to run info command. %s", r.Err)
		return nil, r.Err
	}
	str, err := r.Str()
	if err != nil {
		logger.Errorf("Failed to fetch information. %s", err)
		return nil, err
	}

	stat := make(map[string]interface{})

	keysStat := 0.0
	expiresStat := 0.0
	var slaves []string

	for _, line := range strings.Split(str, "\r\n") {
		if line == "" {
			continue
		}
		if re, _ := regexp.MatchString("^#", line); re {
			continue
		}

		record := strings.SplitN(line, ":", 2)
		if len(record) < 2 {
			continue
		}
		key, value := record[0], record[1]

		if re, _ := regexp.MatchString("^slave\\d+", key); re {
			slaves = append(slaves, key)
			kv := strings.Split(value, ",")
			var offset, lag string
			if len(kv) == 5 {
				_, _, _, offset, lag = kv[0], kv[1], kv[2], kv[3], kv[4]
				lagKv := strings.SplitN(lag, "=", 2)
				lagFv, err := strconv.ParseFloat(lagKv[1], 64)
				if err != nil {
					logger.Warningf("Failed to parse slaves. %s", err)
				}
				stat[fmt.Sprintf("%s_lag", key)] = lagFv
			} else {
				_, _, _, offset = kv[0], kv[1], kv[2], kv[3]
			}
			offsetKv := strings.SplitN(offset, "=", 2)
			offsetFv, err := strconv.ParseFloat(offsetKv[1], 64)
			if err != nil {
				logger.Warningf("Failed to parse slaves. %s", err)
			}
			stat[fmt.Sprintf("%s_offset_delay", key)] = offsetFv
			continue
		}

		if re, _ := regexp.MatchString("^db", key); re {
			kv := strings.SplitN(value, ",", 3)
			keys, expires := kv[0], kv[1]

			keysKv := strings.SplitN(keys, "=", 2)
			keysFv, err := strconv.ParseFloat(keysKv[1], 64)
			if err != nil {
				logger.Warningf("Failed to parse db keys. %s", err)
			}
			keysStat += keysFv

			expiresKv := strings.SplitN(expires, "=", 2)
			expiresFv, err := strconv.ParseFloat(expiresKv[1], 64)
			if err != nil {
				logger.Warningf("Failed to parse db expires. %s", err)
			}
			expiresStat += expiresFv

			continue
		}

		stat[key], err = strconv.ParseFloat(value, 64)
		if err != nil {
			continue
		}
	}

	stat["keys"] = keysStat
	stat["expires"] = expiresStat

	if _, ok := stat["keys"]; !ok {
		stat["keys"] = 0
	}
	if _, ok := stat["expires"]; !ok {
		stat["expires"] = 0
	}

	if _, ok := stat["expired_keys"]; ok {
		stat["expired"] = stat["expired_keys"]
	} else {
		stat["expired"] = 0.0
	}

	if m.ConfigCommand != "" {
		if err := m.calculateCapacity(c, stat); err != nil {
			logger.Infof("Failed to calculate capacity. (The cause may be that AWS Elasticache Redis has no `%s` command.) Skip these metrics. %s", m.ConfigCommand, err)
		}
	}

	for _, slave := range slaves {
		stat[fmt.Sprintf("%s_offset_delay", slave)] = stat["master_repl_offset"].(float64) - stat[fmt.Sprintf("%s_offset_delay", slave)].(float64)
	}

	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (m RedisPlugin) GraphDefinition() map[string]mp.Graphs {
	labelPrefix := strings.Title(m.Prefix)

	var graphdef = map[string]mp.Graphs{
		"queries": {
			Label: (labelPrefix + " Queries"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "total_commands_processed", Label: "Queries", Diff: true},
			},
		},
		"connections": {
			Label: (labelPrefix + " Connections"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "total_connections_received", Label: "Connections", Diff: true, Stacked: true},
				{Name: "rejected_connections", Label: "Rejected Connections", Diff: true, Stacked: true},
			},
		},
		"clients": {
			Label: (labelPrefix + " Clients"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "connected_clients", Label: "Connected Clients", Diff: false, Stacked: true},
				{Name: "blocked_clients", Label: "Blocked Clients", Diff: false, Stacked: true},
				{Name: "connected_slaves", Label: "Connected Slaves", Diff: false, Stacked: true},
			},
		},
		"keys": {
			Label: (labelPrefix + " Keys"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "keys", Label: "Keys", Diff: false},
				{Name: "expires", Label: "Keys with expiration", Diff: false},
				{Name: "expired", Label: "Expired Keys", Diff: true},
			},
		},
		"keyspace": {
			Label: (labelPrefix + " Keyspace"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "keyspace_hits", Label: "Keyspace Hits", Diff: true},
				{Name: "keyspace_misses", Label: "Keyspace Missed", Diff: true},
			},
		},
		"memory": {
			Label: (labelPrefix + " Memory"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "used_memory", Label: "Used Memory", Diff: false},
				{Name: "used_memory_rss", Label: "Used Memory RSS", Diff: false},
				{Name: "used_memory_peak", Label: "Used Memory Peak", Diff: false},
				{Name: "used_memory_lua", Label: "Used Memory Lua engine", Diff: false},
			},
		},
		"capacity": {
			Label: (labelPrefix + " Capacity"),
			Unit:  "percentage",
			Metrics: []mp.Metrics{
				{Name: "percentage_of_memory", Label: "Percentage of memory", Diff: false},
				{Name: "percentage_of_clients", Label: "Percentage of clients", Diff: false},
			},
		},
		"uptime": {
			Label: (labelPrefix + " Uptime"),
			Unit:  "integer",
			Metrics: []mp.Metrics{
				{Name: "uptime_in_seconds", Label: "Uptime In Seconds", Diff: false},
			},
		},
	}

	network := "tcp"
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	if m.Socket != "" {
		target = m.Socket
		network = "unix"
	}

	c, err := redis.DialTimeout(network, target, time.Duration(m.Timeout)*time.Second)
	if err != nil {
		logger.Errorf("Failed to connect redis. %s", err)
		return nil
	}
	defer c.Close()

	if m.Password != "" {
		if err = authenticateByPassword(c, m.Password); err != nil {
			return nil
		}
	}

	r := c.Cmd("info")
	if r.Err != nil {
		logger.Errorf("Failed to run info command. %s", r.Err)
		return nil
	}
	str, err := r.Str()
	if err != nil {
		logger.Errorf("Failed to fetch information. %s", err)
		return nil
	}

	var metricsLag []mp.Metrics
	var metricsOffsetDelay []mp.Metrics
	for _, line := range strings.Split(str, "\r\n") {
		if line == "" {
			continue
		}

		record := strings.SplitN(line, ":", 2)
		if len(record) < 2 {
			continue
		}
		key, _ := record[0], record[1]

		if re, _ := regexp.MatchString("^slave\\d+", key); re {
			metricsLag = append(metricsLag, mp.Metrics{Name: fmt.Sprintf("%s_lag", key), Label: fmt.Sprintf("Replication lag to %s", key), Diff: false})
			metricsOffsetDelay = append(metricsOffsetDelay, mp.Metrics{Name: fmt.Sprintf("%s_offset_delay", key), Label: fmt.Sprintf("Offset delay to %s", key), Diff: false})
		}
	}

	if len(metricsLag) > 0 {
		graphdef["lag"] = mp.Graphs{
			Label:   (labelPrefix + " Slave Lag"),
			Unit:    "seconds",
			Metrics: metricsLag,
		}
	}
	if len(metricsOffsetDelay) > 0 {
		graphdef["offset_delay"] = mp.Graphs{
			Label:   (labelPrefix + " Slave Offset Delay"),
			Unit:    "count",
			Metrics: metricsOffsetDelay,
		}
	}

	return graphdef
}

// Do the plugin
func Do() {
	optHost := flag.String("host", "localhost", "Hostname")
	optPort := flag.String("port", "6379", "Port")
	optPassword := flag.String("password", os.Getenv("REDIS_PASSWORD"), "Password")
	optSocket := flag.String("socket", "", "Server socket (overrides host and port)")
	optPrefix := flag.String("metric-key-prefix", "redis", "Metric key prefix")
	optTimeout := flag.Int("timeout", 5, "Timeout")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	optConfigCommand := flag.String("config-command", "CONFIG", "Custom CONFIG command. Disable CONFIG command when passed \"\".")

	flag.Parse()

	redis := RedisPlugin{
		Timeout:       *optTimeout,
		Prefix:        *optPrefix,
		ConfigCommand: *optConfigCommand,
	}
	if *optSocket != "" {
		redis.Socket = *optSocket
	} else {
		redis.Host = *optHost
		redis.Port = *optPort
		redis.Password = *optPassword
	}
	helper := mp.NewMackerelPlugin(redis)
	helper.Tempfile = *optTempfile

	helper.Run()
}
<|endoftext|>


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

package gitea

// Team is a sub virtual organization of one Organization
type Team struct {
	ID          int64  `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Permission  string `json:"permission"`
}

// CreateTeamOption options when create team
type CreateTeamOption struct {
	Name        string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
	Description string `json:"description" binding:"MaxSize(255)"`
	Permission  string `json:"permission"`
}
<commit_msg>EditTeamOption struct (#25)<commit_after>// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gitea

// Team is a sub virtual organization of one Organization
type Team struct {
	ID          int64  `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Permission  string `json:"permission"`
}

// CreateTeamOption options when create team
type CreateTeamOption struct {
	Name        string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
	Description string `json:"description" binding:"MaxSize(255)"`
	Permission  string `json:"permission"`
}

// EditTeamOption options when edit team
type EditTeamOption struct {
	Name        string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
	Description string `json:"description" binding:"MaxSize(255)"`
	Permission  string `json:"permission"`
}
<|endoftext|>


<commit_before>package publish

import (
	"fmt"
	"net/http"
	"os"
	"path"
	"reflect"
	"strings"

	"github.com/qor/qor/admin"
)

type PublishController struct {
	*DB
}

func (db *PublishController) Preview(context *admin.Context) {
	draftDB := db.DraftMode()
	drafts := make(map[*admin.Resource]interface{})
	for _, model := range db.SupportedModels {
		var res *admin.Resource
		var name = modelType(model).Name()

		if r := context.Admin.GetResource(strings.ToLower(name)); r != nil {
			res = r
		} else {
			res = admin.NewResource(model)
		}

		results := res.NewSlice()
		if draftDB.Unscoped().Where("publish_status = ?", DIRTY).Find(results).RowsAffected > 0 {
			drafts[res] = results
		}
	}
	context.Execute("publish/drafts", drafts)
}

func (db *PublishController) Diff(context *admin.Context) {
	resourceID := strings.Split(context.Request.URL.Path, "/")[4]
	params := strings.Split(resourceID, "__")
	name, id := params[0], params[1]
	res := context.Admin.GetResource(name)

	draft := res.NewStruct()
	db.DraftMode().Unscoped().First(draft, id)

	production := res.NewStruct()
	db.ProductionMode().Unscoped().First(production, id)

	results := map[string]interface{}{"Production": production, "Draft": draft, "Resource": res}

	fmt.Fprintf(context.Writer, context.Render("publish/diff", results))
}

func (db *PublishController) Publish(context *admin.Context) {
	var request = context.Request
	var ids = request.Form["checked_ids[]"]

	if request.Form.Get("publish_type") == "publish" {
		var records = []interface{}{}
		var values = map[string][]string{}

		for _, id := range ids {
			if keys := strings.Split(id, "__"); len(keys) == 2 {
				name, id := keys[0], keys[1]
				values[name] = append(values[name], id)
			}
		}

		for name, value := range values {
			res := context.Admin.GetResource(name)
			results := res.NewSlice()
			if db.DraftMode().Unscoped().Find(results, fmt.Sprintf("%v IN (?)", res.PrimaryKey()), value).Error == nil {
				resultValues := reflect.Indirect(reflect.ValueOf(results))
				for i := 0; i < resultValues.Len(); i++ {
					records = append(records, resultValues.Index(i).Interface())
				}
			}
		}
		db.DB.Publish(records...)
		http.Redirect(context.Writer, context.Request, context.Request.RequestURI, http.StatusFound)
	} else if request.Form.Get("publish_type") == "discard" {
		fmt.Fprint(context.Writer, "not supported yet")
	}
}

func (db *DB) InjectQorAdmin(web *admin.Admin) {
	controller := PublishController{db}
	router := web.GetRouter()
	router.Get("^/publish/diff/", controller.Diff)
	router.Get("^/publish", controller.Preview)
	router.Post("^/publish", controller.Publish)

	for _, gopath := range strings.Split(os.Getenv("GOPATH"), ":") {
		admin.RegisterViewPath(path.Join(gopath, "src/github.com/qor/qor/publish/views"))
	}
}
<commit_msg>Don't show dirty data for unconfiged resources<commit_after>package publish

import (
	"fmt"
	"net/http"
	"os"
	"path"
	"reflect"
	"strings"

	"github.com/qor/qor/admin"
)

type PublishController struct {
	*DB
}

func (db *PublishController) Preview(context *admin.Context) {
	draftDB := db.DraftMode()
	drafts := make(map[*admin.Resource]interface{})
	for _, model := range db.SupportedModels {
		var name = modelType(model).Name()
		if res := context.Admin.GetResource(strings.ToLower(name)); res != nil {
			results := res.NewSlice()
			if draftDB.Unscoped().Where("publish_status = ?", DIRTY).Find(results).RowsAffected > 0 {
				drafts[res] = results
			}
		}
	}
	context.Execute("publish/drafts", drafts)
}

func (db *PublishController) Diff(context *admin.Context) {
	resourceID := strings.Split(context.Request.URL.Path, "/")[4]
	params := strings.Split(resourceID, "__")
	name, id := params[0], params[1]
	res := context.Admin.GetResource(name)

	draft := res.NewStruct()
	db.DraftMode().Unscoped().First(draft, id)

	production := res.NewStruct()
	db.ProductionMode().Unscoped().First(production, id)

	results := map[string]interface{}{"Production": production, "Draft": draft, "Resource": res}

	fmt.Fprintf(context.Writer, context.Render("publish/diff", results))
}

func (db *PublishController) Publish(context *admin.Context) {
	var request = context.Request
	var ids = request.Form["checked_ids[]"]

	if request.Form.Get("publish_type") == "publish" {
		var records = []interface{}{}
		var values = map[string][]string{}

		for _, id := range ids {
			if keys := strings.Split(id, "__"); len(keys) == 2 {
				name, id := keys[0], keys[1]
				values[name] = append(values[name], id)
			}
		}

		for name, value := range values {
			res := context.Admin.GetResource(name)
			results := res.NewSlice()
			if db.DraftMode().Unscoped().Find(results, fmt.Sprintf("%v IN (?)", res.PrimaryKey()), value).Error == nil {
				resultValues := reflect.Indirect(reflect.ValueOf(results))
				for i := 0; i < resultValues.Len(); i++ {
					records = append(records, resultValues.Index(i).Interface())
				}
			}
		}
		db.DB.Publish(records...)
		http.Redirect(context.Writer, context.Request, context.Request.RequestURI, http.StatusFound)
	} else if request.Form.Get("publish_type") == "discard" {
		fmt.Fprint(context.Writer, "not supported yet")
	}
}

func (db *DB) InjectQorAdmin(web *admin.Admin) {
	controller := PublishController{db}
	router := web.GetRouter()
	router.Get("^/publish/diff/", controller.Diff)
	router.Get("^/publish", controller.Preview)
	router.Post("^/publish", controller.Publish)

	for _, gopath := range strings.Split(os.Getenv("GOPATH"), ":") {
		admin.RegisterViewPath(path.Join(gopath, "src/github.com/qor/qor/publish/views"))
	}
}
<|endoftext|>


<commit_before>package resource

import (
	"context"
	"errors"
	"strconv"
	"time"

	"github.com/google/go-github/v32/github"
	"github.com/shurcooL/githubv4"
)

func (g *GitHubClient) listReleasesV4() ([]*github.RepositoryRelease, error) {
	if g.clientV4 == nil {
		return nil, errors.New("github graphql is not been initialised")
	}
	var listReleases struct {
		Repository struct {
			Releases struct {
				Edges []struct {
					Node struct {
						ReleaseObject
					}
				} `graphql:"edges"`
				PageInfo struct {
					EndCursor   githubv4.String
					HasNextPage bool
				} `graphql:"pageInfo"`
			} `graphql:"releases(first:$releasesCount, after: $releaseCursor, orderBy: {field: CREATED_AT, direction: DESC})"`
		} `graphql:"repository(owner:$repositoryOwner,name:$repositoryName)"`
	}

	vars := map[string]interface{}{
		"repositoryOwner": githubv4.String(g.owner),
		"repositoryName":  githubv4.String(g.repository),
		"releaseCursor":   (*githubv4.String)(nil),
		"releasesCount":   githubv4.Int(100),
	}

	var allReleases []*github.RepositoryRelease
	for {
		if err := g.clientV4.Query(context.TODO(), &listReleases, vars); err != nil {
			return nil, err
		}

		for _, r := range listReleases.Repository.Releases.Edges {
			r := r
			publishedAt, _ := time.ParseInLocation(time.RFC3339, r.Node.PublishedAt.Time.Format(time.RFC3339), time.UTC)
			createdAt, _ := time.ParseInLocation(time.RFC3339, r.Node.CreatedAt.Time.Format(time.RFC3339), time.UTC)
			var releaseID int64
			releaseID, err := strconv.ParseInt(r.Node.DatabaseId, 10, 64)
			if err != nil {
				return nil, err
			}
			allReleases = append(allReleases, &github.RepositoryRelease{
				ID:          &releaseID,
				TagName:     &r.Node.TagName,
				Name:        &r.Node.Name,
				Prerelease:  &r.Node.IsPrerelease,
				Draft:       &r.Node.IsDraft,
				URL:         &r.Node.URL,
				PublishedAt: &github.Timestamp{Time: publishedAt},
				CreatedAt:   &github.Timestamp{Time: createdAt},
			})
		}

		if !listReleases.Repository.Releases.PageInfo.HasNextPage {
			break
		}
		vars["releaseCursor"] = listReleases.Repository.Releases.PageInfo.EndCursor
	}

	return allReleases, nil
}
<commit_msg>Update graphql  github release model according to  changes and new fields<commit_after>package resource

import (
	"context"
	"encoding/base64"
	"errors"
	"regexp"
	"strconv"
	"time"

	"github.com/google/go-github/v32/github"
	"github.com/shurcooL/githubv4"
)

func (g *GitHubClient) listReleasesV4() ([]*github.RepositoryRelease, error) {
	if g.clientV4 == nil {
		return nil, errors.New("github graphql is not been initialised")
	}
	var listReleases struct {
		Repository struct {
			Releases struct {
				Edges []struct {
					Node struct {
						ReleaseObject
					}
				} `graphql:"edges"`
				PageInfo struct {
					EndCursor   githubv4.String
					HasNextPage bool
				} `graphql:"pageInfo"`
			} `graphql:"releases(first:$releasesCount, after: $releaseCursor, orderBy: {field: CREATED_AT, direction: DESC})"`
		} `graphql:"repository(owner:$repositoryOwner,name:$repositoryName)"`
	}

	vars := map[string]interface{}{
		"repositoryOwner": githubv4.String(g.owner),
		"repositoryName":  githubv4.String(g.repository),
		"releaseCursor":   (*githubv4.String)(nil),
		"releasesCount":   githubv4.Int(100),
	}

	var allReleases []*github.RepositoryRelease
	for {
		if err := g.clientV4.Query(context.TODO(), &listReleases, vars); err != nil {
			return nil, err
		}

		for _, r := range listReleases.Repository.Releases.Edges {
			r := r
			publishedAt, _ := time.ParseInLocation(time.RFC3339, r.Node.PublishedAt.Time.Format(time.RFC3339), time.UTC)
			createdAt, _ := time.ParseInLocation(time.RFC3339, r.Node.CreatedAt.Time.Format(time.RFC3339), time.UTC)
			var releaseID int64
			if r.Node.DatabaseId == "" {
				decodedID, err := base64.StdEncoding.DecodeString(r.Node.ID)
				if err != nil {
					return nil, err
				}
				re := regexp.MustCompile(`.*[^\d]`)
				decodedID = re.ReplaceAll(decodedID, []byte(""))
				if string(decodedID) == "" {
					return nil, errors.New("bad release id from graph ql api")
				}
				releaseID, err = strconv.ParseInt(string(decodedID), 10, 64)
				if err != nil {
					return nil, err
				}
			} else {
				var id int64
				id, err := strconv.ParseInt(r.Node.DatabaseId, 10, 64)
				if err != nil {
					return nil, err
				}
				releaseID = id
			}

			allReleases = append(allReleases, &github.RepositoryRelease{
				ID:          &releaseID,
				TagName:     &r.Node.TagName,
				Name:        &r.Node.Name,
				Prerelease:  &r.Node.IsPrerelease,
				Draft:       &r.Node.IsDraft,
				URL:         &r.Node.URL,
				PublishedAt: &github.Timestamp{Time: publishedAt},
				CreatedAt:   &github.Timestamp{Time: createdAt},
			})
		}

		if !listReleases.Repository.Releases.PageInfo.HasNextPage {
			break
		}
		vars["releaseCursor"] = listReleases.Repository.Releases.PageInfo.EndCursor
	}

	return allReleases, nil
}
<|endoftext|>


<commit_before>package meep

func Try(fn func(), plan TryPlan) {
	defer func() {
		if err := coerce(recover()); err != nil {
			plan.MustHandle(err)
		}
	}()
	fn()
}

func coerce(rcvrd interface{}) error {
	switch err := rcvrd.(type) {
	case nil:
		// Panics of nils are possible btw but super absurd.  Never do it.
		return nil
	case error:
		return err
	default:
		// Panics of non-error types are bad and you should feel bad.
		return New(&ErrUntypedPanic{Cause: rcvrd})
	}
}

/*
	A wrapper for non-error types raised from a panic.

	The `Try` system will coerce all non-error types to this automatically.
*/
type ErrUntypedPanic struct {
	TraitAutodescribing
	TraitTraceable
	Cause interface{}
}
<commit_msg>Add RecoverPanics helper function that's almost entirely unopinionated.<commit_after>package meep

func RecoverPanics(fn func()) (e error) {
	defer func() {
		e = coerce(recover())
	}()
	fn()
	return
}

func Try(fn func(), plan TryPlan) {
	plan.MustHandle(RecoverPanics(fn))
}

func coerce(rcvrd interface{}) error {
	switch err := rcvrd.(type) {
	case nil:
		// Panics of nils are possible btw but super absurd.  Never do it.
		return nil
	case error:
		return err
	default:
		// Panics of non-error types are bad and you should feel bad.
		return New(&ErrUntypedPanic{Cause: rcvrd})
	}
}

/*
	A wrapper for non-error types raised from a panic.

	The `Try` system will coerce all non-error types to this automatically.
*/
type ErrUntypedPanic struct {
	TraitAutodescribing
	TraitTraceable
	Cause interface{}
}
<|endoftext|>


<commit_before>// Responsible for reading the overall world persistent state.
// Eventually this should also be responsible for writing it as well.
package worldstore

import (
	"compress/gzip"
	"fmt"
	"os"
	"path"

	"chunkymonkey/chunkstore"
	"chunkymonkey/generation"
	. "chunkymonkey/types"
	"chunkymonkey/nbt"
)

type WorldStore struct {
	WorldPath string

	LevelData     *nbt.NamedTag
	ChunkStore    chunkstore.IChunkStore
	StartPosition AbsXyz
}

func LoadWorldStore(worldPath string) (world *WorldStore, err os.Error) {
	levelData, err := loadLevelData(worldPath)
	if err != nil {
		return
	}

	startPosition, err := absXyzFromNbt(levelData, "/Data/Player/Pos")
	if err != nil {
		// TODO Hack - remove this when SMP loading is supported properly.
		startPosition = AbsXyz{ChunkSizeH/2, ChunkSizeY, ChunkSizeH/2}
	}

	var chunkStores []chunkstore.IChunkStore
	persistantChunkStore, err := chunkstore.ChunkStoreForLevel(worldPath, levelData)
	if err != nil {
		return
	}
	chunkStores = append(chunkStores, chunkstore.NewChunkService(persistantChunkStore))

	seed, ok := levelData.Lookup("/Data/RandomSeed").(*nbt.Long)
	if ok {
		chunkStores = append(chunkStores, chunkstore.NewChunkService(generation.NewTestGenerator(seed.Value)))
	}

	for _, store := range chunkStores {
		go store.Serve()
	}

	world = &WorldStore{
		WorldPath:     worldPath,
		LevelData:     levelData,
		ChunkStore:    chunkstore.NewChunkService(chunkstore.NewMultiStore(chunkStores)),
		StartPosition: startPosition,
	}

	go world.ChunkStore.Serve()

	return
}

func loadLevelData(worldPath string) (levelData *nbt.NamedTag, err os.Error) {
	file, err := os.Open(path.Join(worldPath, "level.dat"))
	if err != nil {
		return
	}
	defer file.Close()

	gzipReader, err := gzip.NewReader(file)
	if err != nil {
		return
	}
	defer gzipReader.Close()

	levelData, err = nbt.Read(gzipReader)

	return
}

func absXyzFromNbt(tag nbt.ITag, path string) (pos AbsXyz, err os.Error) {
	posList, posOk := tag.Lookup(path).(*nbt.List)
	if !posOk {
		err = BadType(path)
		return
	}
	x, xOk := posList.Value[0].(*nbt.Double)
	y, yOk := posList.Value[1].(*nbt.Double)
	z, zOk := posList.Value[2].(*nbt.Double)
	if !xOk || !yOk || !zOk {
		err = BadType(path)
		return
	}

	pos = AbsXyz{
		AbsCoord(x.Value),
		AbsCoord(y.Value),
		AbsCoord(z.Value),
	}
	return
}

type BadType string

func (err BadType) String() string {
	return fmt.Sprintf("Bad type in level.dat for %s", string(err))
}
<commit_msg>gofmt run.<commit_after>// Responsible for reading the overall world persistent state.
// Eventually this should also be responsible for writing it as well.
package worldstore

import (
	"compress/gzip"
	"fmt"
	"os"
	"path"

	"chunkymonkey/chunkstore"
	"chunkymonkey/generation"
	. "chunkymonkey/types"
	"chunkymonkey/nbt"
)

type WorldStore struct {
	WorldPath string

	LevelData     *nbt.NamedTag
	ChunkStore    chunkstore.IChunkStore
	StartPosition AbsXyz
}

func LoadWorldStore(worldPath string) (world *WorldStore, err os.Error) {
	levelData, err := loadLevelData(worldPath)
	if err != nil {
		return
	}

	startPosition, err := absXyzFromNbt(levelData, "/Data/Player/Pos")
	if err != nil {
		// TODO Hack - remove this when SMP loading is supported properly.
		startPosition = AbsXyz{ChunkSizeH / 2, ChunkSizeY, ChunkSizeH / 2}
	}

	var chunkStores []chunkstore.IChunkStore
	persistantChunkStore, err := chunkstore.ChunkStoreForLevel(worldPath, levelData)
	if err != nil {
		return
	}
	chunkStores = append(chunkStores, chunkstore.NewChunkService(persistantChunkStore))

	seed, ok := levelData.Lookup("/Data/RandomSeed").(*nbt.Long)
	if ok {
		chunkStores = append(chunkStores, chunkstore.NewChunkService(generation.NewTestGenerator(seed.Value)))
	}

	for _, store := range chunkStores {
		go store.Serve()
	}

	world = &WorldStore{
		WorldPath:     worldPath,
		LevelData:     levelData,
		ChunkStore:    chunkstore.NewChunkService(chunkstore.NewMultiStore(chunkStores)),
		StartPosition: startPosition,
	}

	go world.ChunkStore.Serve()

	return
}

func loadLevelData(worldPath string) (levelData *nbt.NamedTag, err os.Error) {
	file, err := os.Open(path.Join(worldPath, "level.dat"))
	if err != nil {
		return
	}
	defer file.Close()

	gzipReader, err := gzip.NewReader(file)
	if err != nil {
		return
	}
	defer gzipReader.Close()

	levelData, err = nbt.Read(gzipReader)

	return
}

func absXyzFromNbt(tag nbt.ITag, path string) (pos AbsXyz, err os.Error) {
	posList, posOk := tag.Lookup(path).(*nbt.List)
	if !posOk {
		err = BadType(path)
		return
	}
	x, xOk := posList.Value[0].(*nbt.Double)
	y, yOk := posList.Value[1].(*nbt.Double)
	z, zOk := posList.Value[2].(*nbt.Double)
	if !xOk || !yOk || !zOk {
		err = BadType(path)
		return
	}

	pos = AbsXyz{
		AbsCoord(x.Value),
		AbsCoord(y.Value),
		AbsCoord(z.Value),
	}
	return
}

type BadType string

func (err BadType) String() string {
	return fmt.Sprintf("Bad type in level.dat for %s", string(err))
}
<|endoftext|>


<commit_before>// Copyright ©2013 The bíogo.ncbi 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 blast

import (
	"code.google.com/p/biogo.ncbi"
	"code.google.com/p/go.net/html"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
)

// Blast server usage policy requires that users not poll for any single RID more often than once
// a minute. blast package Get requests honour this policy.
const RidPollLimit = 60 * time.Second

// Rid implements RID recovery and waiting functions associated with Blast Put and Get requests.
type Rid struct {
	rid   string
	rtoe  time.Time
	delay <-chan time.Time
	limit *ncbi.Limiter
}

func (rid *Rid) unmarshal(r io.Reader) error {
	z := html.NewTokenizer(r)
	for {
		tt := z.Next()
		if tt == html.ErrorToken {
			return z.Err()
		}
		if tt == html.CommentToken {
			d := z.Token().Data
			if strings.Contains(d, "QBlastInfoBegin") {
				for _, l := range strings.Split(d, "\n") {
					l = strings.TrimSpace(l)
					kv := strings.Split(l, " = ")
					if len(kv) != 2 {
						continue
					}
					switch kv[0] {
					case "RID":
						rid.rid = kv[1]
					case "RTOE":
						rt, err := strconv.ParseInt(kv[1], 10, 64)
						if err != nil {
							return err
						}
						secs := time.Duration(rt) * time.Second
						rid.delay = time.After(secs)
						rid.rtoe = time.Now().Add(secs)
					}
				}
				if rid.rid == "" || rid.delay == nil {
					delay := make(chan time.Time)
					close(delay)
					rid.delay = delay
					return ErrMissingRid
				}
				rid.limit = ncbi.NewLimiter(RidPollLimit)
				return nil
			}
		}
	}
}

// String returns the string representation of the Rid.
func (r *Rid) String() string { return r.rid }

// TimeOfExecution returns the expected time until the request can be satisfied.
func (r *Rid) TimeOfExecution() time.Duration {
	now := time.Now()
	if now.Before(r.rtoe) {
		return r.rtoe.Sub(now)
	}
	return 0
}

// Ready returns a time.Time chan that will send when the estimated time for the
// Put request to be satisfied has elapsed. If the request has failed the channel
// is returned closed.
func (r *Rid) Ready() <-chan time.Time {
	return r.delay
}

// SearchInfo holds search status information.
type SearchInfo struct {
	*Rid
	Status   string
	HaveHits bool
}

func (s *SearchInfo) String() string {
	return fmt.Sprintf("%s Status:%s Hits:%v", s.Rid, s.Status, s.HaveHits)
}

func (s *SearchInfo) unmarshal(r io.Reader) error {
	z := html.NewTokenizer(r)
	for {
		tt := z.Next()
		if tt == html.ErrorToken {
			err := z.Err()
			if err == io.EOF {
				break
			}
			return err
		}
		if tt == html.CommentToken {
			d := z.Token().Data
			if strings.Contains(d, "QBlastInfoBegin") {
				for _, l := range strings.Split(d, "\n") {
					l = strings.TrimSpace(l)
					kv := strings.Split(l, "=")
					if len(kv) != 2 {
						continue
					}
					switch kv[0] {
					case "Status":
						s.Status = kv[1]
					case "ThereAreHits":
						s.HaveHits = true
					}
				}
			}
		}
	}

	if s.Status == "" {
		return ErrMissingStatus
	}
	return nil
}
<commit_msg>Better grammar<commit_after>// Copyright ©2013 The bíogo.ncbi 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 blast

import (
	"code.google.com/p/biogo.ncbi"
	"code.google.com/p/go.net/html"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
)

// Blast server usage policy requires that users not poll for any single RID more often than once
// a minute. The blast package Get requests honour this policy.
const RidPollLimit = 60 * time.Second

// Rid implements RID recovery and waiting functions associated with Blast Put and Get requests.
type Rid struct {
	rid   string
	rtoe  time.Time
	delay <-chan time.Time
	limit *ncbi.Limiter
}

func (rid *Rid) unmarshal(r io.Reader) error {
	z := html.NewTokenizer(r)
	for {
		tt := z.Next()
		if tt == html.ErrorToken {
			return z.Err()
		}
		if tt == html.CommentToken {
			d := z.Token().Data
			if strings.Contains(d, "QBlastInfoBegin") {
				for _, l := range strings.Split(d, "\n") {
					l = strings.TrimSpace(l)
					kv := strings.Split(l, " = ")
					if len(kv) != 2 {
						continue
					}
					switch kv[0] {
					case "RID":
						rid.rid = kv[1]
					case "RTOE":
						rt, err := strconv.ParseInt(kv[1], 10, 64)
						if err != nil {
							return err
						}
						secs := time.Duration(rt) * time.Second
						rid.delay = time.After(secs)
						rid.rtoe = time.Now().Add(secs)
					}
				}
				if rid.rid == "" || rid.delay == nil {
					delay := make(chan time.Time)
					close(delay)
					rid.delay = delay
					return ErrMissingRid
				}
				rid.limit = ncbi.NewLimiter(RidPollLimit)
				return nil
			}
		}
	}
}

// String returns the string representation of the Rid.
func (r *Rid) String() string { return r.rid }

// TimeOfExecution returns the expected time until the request can be satisfied.
func (r *Rid) TimeOfExecution() time.Duration {
	now := time.Now()
	if now.Before(r.rtoe) {
		return r.rtoe.Sub(now)
	}
	return 0
}

// Ready returns a time.Time chan that will send when the estimated time for the
// Put request to be satisfied has elapsed. If the request has failed the channel
// is returned closed.
func (r *Rid) Ready() <-chan time.Time {
	return r.delay
}

// SearchInfo holds search status information.
type SearchInfo struct {
	*Rid
	Status   string
	HaveHits bool
}

func (s *SearchInfo) String() string {
	return fmt.Sprintf("%s Status:%s Hits:%v", s.Rid, s.Status, s.HaveHits)
}

func (s *SearchInfo) unmarshal(r io.Reader) error {
	z := html.NewTokenizer(r)
	for {
		tt := z.Next()
		if tt == html.ErrorToken {
			err := z.Err()
			if err == io.EOF {
				break
			}
			return err
		}
		if tt == html.CommentToken {
			d := z.Token().Data
			if strings.Contains(d, "QBlastInfoBegin") {
				for _, l := range strings.Split(d, "\n") {
					l = strings.TrimSpace(l)
					kv := strings.Split(l, "=")
					if len(kv) != 2 {
						continue
					}
					switch kv[0] {
					case "Status":
						s.Status = kv[1]
					case "ThereAreHits":
						s.HaveHits = true
					}
				}
			}
		}
	}

	if s.Status == "" {
		return ErrMissingStatus
	}
	return nil
}
<|endoftext|>


<commit_before>package blob

import (
  "github.com/loldesign/azure/core"
  "net/http"
  "time"
  "log"
)

type Azure struct {
  Account string
  AccessKey string
}

func (azure Azure) prepareRequest(method, container, resource string) *http.Request {
  core := core.Core{
      AccessKey: azure.AccessKey,
      Account: azure.Account,
      Method: method,
      RequestTime: time.Now().UTC(),
      Container: container,
      Resource: resource}

  return core.PrepareRequest()
}

func (azure Azure) CreateContainer(container string) *http.Response {
  client := &http.Client{}
  req := azure.prepareRequest("put", container, "?restype=container")

  res, err := client.Do(req)

  if err != nil {
    log.Fatal(err)
  }

  return res
}

func (azure Azure) DeleteContainer(container string) *http.Response {
  client := &http.Client{}
  req := azure.prepareRequest("delete", container, "?restype=container")

  res, err := client.Do(req)

  if err != nil {
    log.Fatal(err)
  }

  return res
}
<commit_msg>using the new core approach and refactoring public methods<commit_after>package blob

import (
  "github.com/loldesign/azure/core"
  "net/http"
  "fmt"
  "time"
  "io"
)

type Azure struct {
  Account string
  AccessKey string
}

func (azure Azure) doRequest(azureRequest core.AzureRequest) (*http.Response, error) {
  client, req := azure.clientAndRequest(azureRequest)
  return client.Do(req)
}

func (azure Azure) clientAndRequest(azureRequest core.AzureRequest) (*http.Client, *http.Request) {
  client := &http.Client{}
  req := azure.prepareRequest(azureRequest)

  return client, req
}

func (azure Azure) prepareRequest(azureRequest core.AzureRequest) *http.Request {
  credentials := core.Credentials{
    Account: azure.Account,
    AccessKey: azure.AccessKey}

  return core.New(credentials, azureRequest).PrepareRequest()
}

func (azure Azure) CreateContainer(container string) (*http.Response, error) {
  azureRequest := core.AzureRequest{
    Method: "put",
    Container: container,
    Resource: "?restype=container",
    RequestTime: time.Now().UTC()}

  return azure.doRequest(azureRequest)
}

func (azure Azure) DeleteContainer(container string) (*http.Response, error) {
  azureRequest := core.AzureRequest{
    Method: "delete",
    Container: container,
    Resource: "?restype=container",
    RequestTime: time.Now().UTC()}

  return azure.doRequest(azureRequest)
}

func (azure Azure) FileUpload(container, name string, body io.Reader) (*http.Response, error) {
  azureRequest := core.AzureRequest{
    Method: "put",
    Container: fmt.Sprintf("%s/%s", container, name),
    Body: body,
    Header: map[string]string{"x-ms-blob-type": "BlockBlob", "Accept-Charset": "UTF-8"},
    RequestTime: time.Now().UTC()}

  return azure.doRequest(azureRequest)
}<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
)

func Log(req *http.Request) {
	log.Println(req.URL, req.UserAgent(), req.Form)
}

func Home(w http.ResponseWriter, req *http.Request) {
	w.Write([]byte("Hello World"))
	Log(req)
}

func TradeOpen(w http.ResponseWriter, req *http.Request) {
	log.Println(req.FormValue("q"))
	w.Write([]byte(req.FormValue("q")))
	Log(req)
}

func main() {
	http.HandleFunc("/", Home)
	http.HandleFunc("/open", TradeOpen)
	log.Fatal(http.ListenAndServe(":59123", nil))
}
<commit_msg>Add conv to date.<commit_after>package main

import (
	"log"
	"net/http"
	"strconv"
	"time"
)

func Log(req *http.Request) {
	log.Println(req.URL, req.UserAgent(), req.Form)
}

func Home(w http.ResponseWriter, req *http.Request) {
	w.Write([]byte("Hello World"))
	Log(req)
}

func TradeOpen(w http.ResponseWriter, req *http.Request) {
	data, err := strconv.ParseInt(req.FormValue("q"), 10, 64)
	if err != nil {
		w.Write([]byte("Wrong data format."))
	} else {
		date := time.Unix(data, 0)
		w.Write([]byte(date.String()))
	}
	Log(req)
}

func main() {
	http.HandleFunc("/", Home)
	http.HandleFunc("/open", TradeOpen)
	log.Fatal(http.ListenAndServe(":59123", nil))
}
<|endoftext|>


<commit_before>package main

import tui "github.com/gizak/termui"

type TreeItem struct {
	n       *DepsNode
	parent  *TreeItem
	sibling *TreeItem
	child   *TreeItem // pointer to first child
	folded  bool
	total   int // number of (shown) children (not count itself)
}

type ScrollList struct {
	tui.Block // embedded
	Items     *TreeItem
	Curr      *TreeItem

	ItemFgColor  tui.Attribute
	ItemBgColor  tui.Attribute
	FocusFgColor tui.Attribute
	FocusBgColor tui.Attribute

	idx int // current cursor position
	off int // first entry displayed
}

func NewScrollList() *ScrollList {
	l := &ScrollList{Block: *tui.NewBlock()}
	l.ItemFgColor = tui.ThemeAttr("list.item.fg")
	l.ItemBgColor = tui.ThemeAttr("list.item.bg")
	l.FocusFgColor = tui.ColorYellow
	l.FocusBgColor = tui.ColorBlue

	l.idx = 0
	l.off = 0
	return l
}

func (i *TreeItem) next() *TreeItem {
	if i.child == nil || i.folded {
		for i != nil {
			if i.sibling != nil {
				return i.sibling
			}

			i = i.parent
		}
		return nil
	}
	return i.child
}

func (i *TreeItem) expand() {
	if !i.folded || i.child == nil {
		return
	}

	for c := i.child; c != nil; c = c.sibling {
		i.total += c.total + 1
	}

	for p := i.parent; p != nil; p = p.parent {
		p.total += i.total
	}

	i.folded = false
}

func (i *TreeItem) fold() {
	if i.folded || i.child == nil {
		return
	}

	for p := i.parent; p != nil; p = p.parent {
		p.total -= i.total
	}
	i.total = 0

	i.folded = true
}

func (i *TreeItem) toggle() {
	if i.folded {
		i.expand()
	} else {
		i.fold()
	}
}

// Buffer implements Bufferer interface.
func (l *ScrollList) Buffer() tui.Buffer {
	buf := l.Block.Buffer()

	i := 0
	printed := 0

	var ti *TreeItem
	for ti = l.Items; ti != nil; ti = ti.next() {
		if i < l.off {
			i++
			continue
		}
		if printed == l.Height-2 {
			break
		}

		fg := l.ItemFgColor
		bg := l.ItemBgColor
		if i == l.idx {
			fg = l.FocusFgColor
			bg = l.FocusBgColor

			l.Curr = ti
		}

		cs := tui.DefaultTxBuilder.Build(ti.n.name, fg, bg)
		cs = tui.DTrimTxCls(cs, l.Width-2-2-3*ti.n.depth)

		j := 0
		if i == l.idx {
			// draw current line cursor from the beginning
			for j < 3*ti.n.depth {
				buf.Set(j+1, printed+1, tui.Cell{' ', fg, bg})
				j++
			}
		} else {
			j = 3 * ti.n.depth
		}

		if ti.folded {
			buf.Set(j+1, printed+1, tui.Cell{'+', fg, bg})
		} else {
			buf.Set(j+1, printed+1, tui.Cell{'-', fg, bg})
		}
		buf.Set(j+2, printed+1, tui.Cell{' ', fg, bg})
		j += 2

		for _, vv := range cs {
			w := vv.Width()
			buf.Set(j+1, printed+1, vv)
			j += w
		}

		printed++
		i++

		if i != l.idx+1 {
			continue
		}

		// draw current line cursor to the end
		for j < l.Width-2 {
			buf.Set(j+1, printed, tui.Cell{' ', fg, bg})
			j++
		}
	}
	return buf
}

func (l *ScrollList) Down() {
	if l.idx < l.Items.total {
		l.idx++
	}
	if l.idx-l.off >= l.Height-2 {
		l.off++
	}
}

func (l *ScrollList) Up() {
	if l.idx > 0 {
		l.idx--
	}
	if l.idx < l.off {
		l.off = l.idx
	}
}

func (l *ScrollList) PageDown() {
	bottom := l.off + (l.Height - 2) - 1
	if bottom > l.Items.total {
		bottom = l.Items.total
	}

	// At first, move to the bottom of current page
	if l.idx != bottom {
		l.idx = bottom
		return
	}

	l.idx += l.Height - 2
	if l.idx > l.Items.total {
		l.idx = l.Items.total
	}
	if l.idx-l.off >= l.Height-2 {
		l.off = l.idx - (l.Height - 2) + 1
	}
}

func (l *ScrollList) PageUp() {
	// At first, move to the top of current page
	if l.idx != l.off {
		l.idx = l.off
		return
	}

	l.idx -= l.Height - 2
	if l.idx < 0 {
		l.idx = 0
	}

	l.off = l.idx
}

func (l *ScrollList) Home() {
	l.idx = 0
	l.off = 0
}

func (l *ScrollList) End() {
	l.idx = l.Items.total
	l.off = l.idx - (l.Height - 2) + 1

	if l.off < 0 {
		l.off = 0
	}
}

func (l *ScrollList) Toggle() {
	l.Curr.toggle()
}

func makeItems(dep *DepsNode, parent *TreeItem) *TreeItem {
	item := &TreeItem{n: dep, parent: parent, folded: false, total: len(dep.child)}

	var prev *TreeItem
	for _, v := range dep.child {
		c := makeItems(v, item)

		if item.child == nil {
			item.child = c
		}
		if prev != nil {
			prev.sibling = c
		}
		prev = c

		item.total += c.total
	}
	return item
}

func ShowWithTUI(dep *DepsNode) {
	if err := tui.Init(); err != nil {
		panic(err)
	}
	defer tui.Close()

	items := makeItems(dep, nil)

	ls := NewScrollList()

	ls.BorderLabel = "Tree view"
	ls.Height = tui.TermHeight()
	ls.Width = tui.TermWidth()
	ls.Items = items
	ls.Curr = items

	tui.Render(ls)

	// handle key pressing
	tui.Handle("/sys/kbd/q", func(tui.Event) {
		// press q to quit
		tui.StopLoop()
	})
	tui.Handle("/sys/kbd/C-c", func(tui.Event) {
		// press Ctrl-C to quit
		tui.StopLoop()
	})

	tui.Handle("/sys/kbd/<down>", func(tui.Event) {
		ls.Down()
		tui.Render(ls)
	})
	tui.Handle("/sys/kbd/<up>", func(tui.Event) {
		ls.Up()
		tui.Render(ls)
	})
	tui.Handle("/sys/kbd/<next>", func(tui.Event) {
		ls.PageDown()
		tui.Render(ls)
	})
	tui.Handle("/sys/kbd/<previous>", func(tui.Event) {
		ls.PageUp()
		tui.Render(ls)
	})
	tui.Handle("/sys/kbd/<home>", func(tui.Event) {
		ls.Home()
		tui.Render(ls)
	})
	tui.Handle("/sys/kbd/<end>", func(tui.Event) {
		ls.End()
		tui.Render(ls)
	})

	tui.Handle("/sys/kbd/<enter>", func(tui.Event) {
		ls.Toggle()
		tui.Render(ls)
	})

	tui.Handle("/sys/wnd/resize", func(tui.Event) {
		ls.Height = tui.TermHeight()
		ls.Width = tui.TermWidth()
		tui.Render(ls)
	})

	tui.Loop()
}
<commit_msg>Rename data structure to TreeView<commit_after>package main

import tui "github.com/gizak/termui"

type TreeItem struct {
	node    *DepsNode
	parent  *TreeItem
	sibling *TreeItem
	child   *TreeItem // pointer to first child
	folded  bool
	total   int // number of (shown) children (not count itself)
}

type TreeView struct {
	tui.Block // embedded
	Root      *TreeItem
	Curr      *TreeItem

	ItemFgColor  tui.Attribute
	ItemBgColor  tui.Attribute
	FocusFgColor tui.Attribute
	FocusBgColor tui.Attribute

	idx int // current cursor position
	off int // first entry displayed
}

func NewTreeView() *TreeView {
	tv := &TreeView{Block: *tui.NewBlock()}

	tv.ItemFgColor = tui.ThemeAttr("list.item.fg")
	tv.ItemBgColor = tui.ThemeAttr("list.item.bg")
	tv.FocusFgColor = tui.ColorYellow
	tv.FocusBgColor = tui.ColorBlue

	tv.idx = 0
	tv.off = 0
	return tv
}

func (ti *TreeItem) next() *TreeItem {
	if ti.child == nil || ti.folded {
		for ti != nil {
			if ti.sibling != nil {
				return ti.sibling
			}

			ti = ti.parent
		}
		return nil
	}
	return ti.child
}

func (ti *TreeItem) expand() {
	if !ti.folded || ti.child == nil {
		return
	}

	for c := ti.child; c != nil; c = c.sibling {
		ti.total += c.total + 1
	}

	for p := ti.parent; p != nil; p = p.parent {
		p.total += ti.total
	}

	ti.folded = false
}

func (ti *TreeItem) fold() {
	if ti.folded || ti.child == nil {
		return
	}

	for p := ti.parent; p != nil; p = p.parent {
		p.total -= ti.total
	}
	ti.total = 0

	ti.folded = true
}

func (ti *TreeItem) toggle() {
	if ti.folded {
		ti.expand()
	} else {
		ti.fold()
	}
}

// Buffer implements Bufferer interface.
func (tv *TreeView) Buffer() tui.Buffer {
	buf := tv.Block.Buffer()

	i := 0
	printed := 0

	var ti *TreeItem
	for ti = tv.Root; ti != nil; ti = ti.next() {
		if i < tv.off {
			i++
			continue
		}
		if printed == tv.Height-2 {
			break
		}

		fg := tv.ItemFgColor
		bg := tv.ItemBgColor
		if i == tv.idx {
			fg = tv.FocusFgColor
			bg = tv.FocusBgColor

			tv.Curr = ti
		}

		indent := 3 * ti.node.depth
		cs := tui.DefaultTxBuilder.Build(ti.node.name, fg, bg)
		cs = tui.DTrimTxCls(cs, (tv.Width-2)-2-indent)

		j := 0
		if i == tv.idx {
			// draw current line cursor from the beginning
			for j < indent {
				buf.Set(j+1, printed+1, tui.Cell{' ', fg, bg})
				j++
			}
		} else {
			j = indent
		}

		if ti.folded {
			buf.Set(j+1, printed+1, tui.Cell{'+', fg, bg})
		} else {
			buf.Set(j+1, printed+1, tui.Cell{'-', fg, bg})
		}
		buf.Set(j+2, printed+1, tui.Cell{' ', fg, bg})
		j += 2

		for _, vv := range cs {
			w := vv.Width()
			buf.Set(j+1, printed+1, vv)
			j += w
		}

		printed++
		i++

		if i != tv.idx+1 {
			continue
		}

		// draw current line cursor to the end
		for j < tv.Width-2 {
			buf.Set(j+1, printed, tui.Cell{' ', fg, bg})
			j++
		}
	}
	return buf
}

func (tv *TreeView) Down() {
	if tv.idx < tv.Root.total {
		tv.idx++
	}
	if tv.idx-tv.off >= tv.Height-2 {
		tv.off++
	}
}

func (tv *TreeView) Up() {
	if tv.idx > 0 {
		tv.idx--
	}
	if tv.idx < tv.off {
		tv.off = tv.idx
	}
}

func (tv *TreeView) PageDown() {
	bottom := tv.off + (tv.Height - 2) - 1
	if bottom > tv.Root.total {
		bottom = tv.Root.total
	}

	// At first, move to the bottom of current page
	if tv.idx != bottom {
		tv.idx = bottom
		return
	}

	tv.idx += tv.Height - 2
	if tv.idx > tv.Root.total {
		tv.idx = tv.Root.total
	}
	if tv.idx-tv.off >= tv.Height-2 {
		tv.off = tv.idx - (tv.Height - 2) + 1
	}
}

func (tv *TreeView) PageUp() {
	// At first, move to the top of current page
	if tv.idx != tv.off {
		tv.idx = tv.off
		return
	}

	tv.idx -= tv.Height - 2
	if tv.idx < 0 {
		tv.idx = 0
	}

	tv.off = tv.idx
}

func (tv *TreeView) Home() {
	tv.idx = 0
	tv.off = 0
}

func (tv *TreeView) End() {
	tv.idx = tv.Root.total
	tv.off = tv.idx - (tv.Height - 2) + 1

	if tv.off < 0 {
		tv.off = 0
	}
}

func (tv *TreeView) Toggle() {
	tv.Curr.toggle()
}

func makeItems(dep *DepsNode, parent *TreeItem) *TreeItem {
	item := &TreeItem{node: dep, parent: parent, folded: false, total: len(dep.child)}

	var prev *TreeItem
	for _, v := range dep.child {
		c := makeItems(v, item)

		if item.child == nil {
			item.child = c
		}
		if prev != nil {
			prev.sibling = c
		}
		prev = c

		item.total += c.total
	}
	return item
}

func ShowWithTUI(dep *DepsNode) {
	if err := tui.Init(); err != nil {
		panic(err)
	}
	defer tui.Close()

	root := makeItems(dep, nil)

	tv := NewTreeView()

	tv.BorderLabel = "ELF Tree"
	tv.Height = tui.TermHeight()
	tv.Width = tui.TermWidth()
	tv.Root = root
	tv.Curr = root

	tui.Render(tv)

	// handle key pressing
	tui.Handle("/sys/kbd/q", func(tui.Event) {
		// press q to quit
		tui.StopLoop()
	})
	tui.Handle("/sys/kbd/C-c", func(tui.Event) {
		// press Ctrl-C to quit
		tui.StopLoop()
	})

	tui.Handle("/sys/kbd/<down>", func(tui.Event) {
		tv.Down()
		tui.Render(tv)
	})
	tui.Handle("/sys/kbd/<up>", func(tui.Event) {
		tv.Up()
		tui.Render(tv)
	})
	tui.Handle("/sys/kbd/<next>", func(tui.Event) {
		tv.PageDown()
		tui.Render(tv)
	})
	tui.Handle("/sys/kbd/<previous>", func(tui.Event) {
		tv.PageUp()
		tui.Render(tv)
	})
	tui.Handle("/sys/kbd/<home>", func(tui.Event) {
		tv.Home()
		tui.Render(tv)
	})
	tui.Handle("/sys/kbd/<end>", func(tui.Event) {
		tv.End()
		tui.Render(tv)
	})

	tui.Handle("/sys/kbd/<enter>", func(tui.Event) {
		tv.Toggle()
		tui.Render(tv)
	})

	tui.Handle("/sys/wnd/resize", func(tui.Event) {
		tv.Height = tui.TermHeight()
		tv.Width = tui.TermWidth()
		tui.Render(tv)
	})

	tui.Loop()
}
<|endoftext|>


<commit_before>package spec

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestPropertySerialization(t *testing.T) {

	Convey("Properties should serialize", t, func() {
		Convey("a boolean property", func() {
			prop := BooleanProperty()
			So(prop, ShouldSerializeJSON, `{"type":"boolean"}`)
		})
		Convey("a date property", func() {
			prop := DateProperty()
			So(prop, ShouldSerializeJSON, `{"type":"string","format":"date"}`)
		})
		Convey("a date-time property", func() {
			prop := DateTimeProperty()
			So(prop, ShouldSerializeJSON, `{"type":"string","format":"date-time"}`)
		})
		Convey("a float64 property", func() {
			prop := Float64Property()
			So(prop, ShouldSerializeJSON, `{"type":"number","format":"double"}`)
		})
		Convey("a float32 property", func() {
			prop := Float32Property()
			So(prop, ShouldSerializeJSON, `{"type":"number","format":"float"}`)
		})
		Convey("a int32 property", func() {
			prop := Int32Property()
			So(prop, ShouldSerializeJSON, `{"type":"number","format":"int32"}`)
		})
		Convey("a int64 property", func() {
			prop := Int64Property()
			So(prop, ShouldSerializeJSON, `{"type":"number","format":"int64"}`)
		})
		Convey("a string map property", func() {
			prop := MapProperty(StringProperty())
			So(prop, ShouldSerializeJSON, `{"type":"object","additionalProperties":{"type":"string"}}`)
		})
		Convey("an int32 map property", func() {
			prop := MapProperty(Int32Property())
			So(prop, ShouldSerializeJSON, `{"type":"object","additionalProperties":{"type":"number","format":"int32"}}`)
		})
		Convey("a ref property", func() {
			prop := RefProperty("Dog")
			So(prop, ShouldSerializeJSON, `{"$ref":"Dog"}`)
		})
		Convey("a string property", func() {
			prop := StringProperty()
			So(prop, ShouldSerializeJSON, `{"type":"string"}`)
		})
		Convey("a string property with enums", func() {
			prop := StringProperty()
			prop.Enum = append(prop.Enum, "a", "b")
			So(prop, ShouldSerializeJSON, `{"type":"string","enum":["a","b"]}`)
		})
		Convey("a string array property", func() {
			prop := ArrayProperty(StringProperty())
			So(prop, ShouldSerializeJSON, `{"type":"array","items":{"type":"string"}}`)
		})
	})

	Convey("Properties should deserialize", t, func() {
		Convey("a boolean property", func() {
			prop := BooleanProperty()
			So(`{"type":"boolean"}`, ShouldParseJSON, prop)
		})
		Convey("a date property", func() {
			prop := DateProperty()
			So(`{"format":"date","type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a date-time property", func() {
			prop := DateTimeProperty()
			So(`{"format":"date-time","type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a float64 property", func() {
			prop := Float64Property()
			So(`{"format":"double","type":"number"}`, ShouldParseJSON, prop)
		})
		Convey("a float32 property", func() {
			prop := Float32Property()
			So(`{"format":"float","type":"number"}`, ShouldParseJSON, prop)
		})
		Convey("a int32 property", func() {
			prop := Int32Property()
			So(`{"format":"int32","type":"number"}`, ShouldParseJSON, prop)
		})
		Convey("a int64 property", func() {
			prop := Int64Property()
			So(`{"format":"int64","type":"number"}`, ShouldParseJSON, prop)
		})
		Convey("a string map property", func() {
			prop := MapProperty(StringProperty())
			So(`{"additionalProperties":{"type":"string"},"type":"object"}`, ShouldParseJSON, prop)
		})
		Convey("an int32 map property", func() {
			prop := MapProperty(Int32Property())
			So(`{"additionalProperties":{"format":"int32","type":"number"},"type":"object"}`, ShouldParseJSON, prop)
		})
		Convey("a ref property", func() {
			prop := RefProperty("Dog")
			So(`{"$ref":"Dog"}`, ShouldParseJSON, prop)
		})
		Convey("a string property", func() {
			prop := StringProperty()
			So(`{"type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a string property with enums", func() {
			prop := StringProperty()
			prop.Enum = append(prop.Enum, "a", "b")
			So(`{"enum":["a","b"],"type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a string array property", func() {
			prop := ArrayProperty(StringProperty())
			So(`{"items":{"type":"string"},"type":"array"}`, ShouldParseJSON, prop)
		})
		Convey("a list of string array properties", func() {
			prop := &Schema{schemaProps: schemaProps{
				Items: &SchemaOrArray{Schemas: []Schema{
					Schema{schemaProps: schemaProps{Type: []string{"string"}}},
					Schema{schemaProps: schemaProps{Type: []string{"string"}}},
				}},
			}}
			So(`{"items":[{"type":"string"},{"type":"string"}]}`, ShouldParseJSON, prop)
		})
	})
}
<commit_msg>Fix tests for integer<commit_after>package spec

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestPropertySerialization(t *testing.T) {

	Convey("Properties should serialize", t, func() {
		Convey("a boolean property", func() {
			prop := BooleanProperty()
			So(prop, ShouldSerializeJSON, `{"type":"boolean"}`)
		})
		Convey("a date property", func() {
			prop := DateProperty()
			So(prop, ShouldSerializeJSON, `{"type":"string","format":"date"}`)
		})
		Convey("a date-time property", func() {
			prop := DateTimeProperty()
			So(prop, ShouldSerializeJSON, `{"type":"string","format":"date-time"}`)
		})
		Convey("a float64 property", func() {
			prop := Float64Property()
			So(prop, ShouldSerializeJSON, `{"type":"number","format":"double"}`)
		})
		Convey("a float32 property", func() {
			prop := Float32Property()
			So(prop, ShouldSerializeJSON, `{"type":"number","format":"float"}`)
		})
		Convey("a int32 property", func() {
			prop := Int32Property()
			So(prop, ShouldSerializeJSON, `{"type":"integer","format":"int32"}`)
		})
		Convey("a int64 property", func() {
			prop := Int64Property()
			So(prop, ShouldSerializeJSON, `{"type":"integer","format":"int64"}`)
		})
		Convey("a string map property", func() {
			prop := MapProperty(StringProperty())
			So(prop, ShouldSerializeJSON, `{"type":"object","additionalProperties":{"type":"string"}}`)
		})
		Convey("an int32 map property", func() {
			prop := MapProperty(Int32Property())
			So(prop, ShouldSerializeJSON, `{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}`)
		})
		Convey("a ref property", func() {
			prop := RefProperty("Dog")
			So(prop, ShouldSerializeJSON, `{"$ref":"Dog"}`)
		})
		Convey("a string property", func() {
			prop := StringProperty()
			So(prop, ShouldSerializeJSON, `{"type":"string"}`)
		})
		Convey("a string property with enums", func() {
			prop := StringProperty()
			prop.Enum = append(prop.Enum, "a", "b")
			So(prop, ShouldSerializeJSON, `{"type":"string","enum":["a","b"]}`)
		})
		Convey("a string array property", func() {
			prop := ArrayProperty(StringProperty())
			So(prop, ShouldSerializeJSON, `{"type":"array","items":{"type":"string"}}`)
		})
	})

	Convey("Properties should deserialize", t, func() {
		Convey("a boolean property", func() {
			prop := BooleanProperty()
			So(`{"type":"boolean"}`, ShouldParseJSON, prop)
		})
		Convey("a date property", func() {
			prop := DateProperty()
			So(`{"format":"date","type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a date-time property", func() {
			prop := DateTimeProperty()
			So(`{"format":"date-time","type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a float64 property", func() {
			prop := Float64Property()
			So(`{"format":"double","type":"number"}`, ShouldParseJSON, prop)
		})
		Convey("a float32 property", func() {
			prop := Float32Property()
			So(`{"format":"float","type":"number"}`, ShouldParseJSON, prop)
		})
		Convey("a int32 property", func() {
			prop := Int32Property()
			So(`{"format":"int32","type":"integer"}`, ShouldParseJSON, prop)
		})
		Convey("a int64 property", func() {
			prop := Int64Property()
			So(`{"format":"int64","type":"integer"}`, ShouldParseJSON, prop)
		})
		Convey("a string map property", func() {
			prop := MapProperty(StringProperty())
			So(`{"additionalProperties":{"type":"string"},"type":"object"}`, ShouldParseJSON, prop)
		})
		Convey("an int32 map property", func() {
			prop := MapProperty(Int32Property())
			So(`{"additionalProperties":{"format":"int32","type":"integer"},"type":"object"}`, ShouldParseJSON, prop)
		})
		Convey("a ref property", func() {
			prop := RefProperty("Dog")
			So(`{"$ref":"Dog"}`, ShouldParseJSON, prop)
		})
		Convey("a string property", func() {
			prop := StringProperty()
			So(`{"type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a string property with enums", func() {
			prop := StringProperty()
			prop.Enum = append(prop.Enum, "a", "b")
			So(`{"enum":["a","b"],"type":"string"}`, ShouldParseJSON, prop)
		})
		Convey("a string array property", func() {
			prop := ArrayProperty(StringProperty())
			So(`{"items":{"type":"string"},"type":"array"}`, ShouldParseJSON, prop)
		})
		Convey("a list of string array properties", func() {
			prop := &Schema{schemaProps: schemaProps{
				Items: &SchemaOrArray{Schemas: []Schema{
					Schema{schemaProps: schemaProps{Type: []string{"string"}}},
					Schema{schemaProps: schemaProps{Type: []string{"string"}}},
				}},
			}}
			So(`{"items":[{"type":"string"},{"type":"string"}]}`, ShouldParseJSON, prop)
		})
	})
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
)

type UDP_manager struct {
    ipAddress string
    write *IP_Writer
    read  *IP_Reader
    buff      map[uint16](chan []byte)
}

type UDP struct {
    manager   *UDP_manager
    bytes     chan []byte
    src, dest uint16 // ports
}

func NewUDP_Manager(ip string) (*UDP_manager, error) {
    //p, err := net.ListenPacket("ip4:1", ip)
    //if err != nil {
    //    fmt.Println(err)
    //    return nil, err
    //}

    // TODO: Separate the server UDP and client UDP connections

    ipw, err := NewIP_Writer(ip, 17) // 17 for UDP
    if err != nil {
        return nil, err
    }

    nr, err := NewNetwork_Reader()
    if err != nil {
        return nil, err
    }

    ipr, err := nr.NewIP_Reader(ip, 17) // 17 for UDP
    if err != nil {
        return nil, err;
    }

    x := &UDP_manager{
        read: ipr,
        write: ipw,
        buff: make(map[uint16](chan []byte)),
        ipAddress: ip,
    }

    go x.readAll()

    return x, nil
}

func (x *UDP_manager) readAll() {
    for {
        _, payload, err := x.read.ReadFrom()
        if err != nil {
            continue
        }
        //        fmt.Println(b)
        fmt.Println("UDP header and payload: ", payload)

        dest := (((uint16)(payload[2])) * 256) + ((uint16)(payload[3]))
        //		fmt.Println(dest)
        //		fmt.Println(payload)
        //
        //		fmt.Println(x.buff)
        c, ok := x.buff[dest]
        //fmt.Println(ok)
        payload = payload[8:]
        if ok {
            go func() {
                c <- payload
            }()
        }
    }
}

func (x *UDP_manager) NewUDP(src, dest uint16) (*UDP, error) {
    x.buff[src] = make(chan byte, 1024)
    return &UDP{src: src, dest: dest, bytes: x.buff[src], manager: x}, nil
}

func (c *UDP) read(size int) ([]byte, error) {
    data := <- c.bytes
    if len(data) > size {
        data = data[:size]
    }
    return data, nil
}
func (c *UDP) write(x []byte) error {
    UDPHeader := []byte{
        (byte)(c.src >> 8), (byte)(c.src), // Source port in byte slice
        (byte)(c.dest >> 8), (byte)(c.dest), // Dest port in byte slice
        (byte)((8 + len(x)) >> 8), (byte)(8 + len(x)), // Length in bytes of UDP header + data
        0, 0, // Checksum
    }

    x = append(UDPHeader, x...)

    err := c.manager.write.WriteTo(x)
    if err != nil {
        fmt.Println(err)
        return err
    }
    return nil
}
func (c *UDP) close() error {
    delete(c.manager.buff, c.src)
    return nil
}
<commit_msg>Error fix<commit_after>package main

import (
    "fmt"
)

type UDP_manager struct {
    ipAddress string
    write *IP_Writer
    read  *IP_Reader
    buff      map[uint16](chan []byte)
}

type UDP struct {
    manager   *UDP_manager
    bytes     chan []byte
    src, dest uint16 // ports
}

func NewUDP_Manager(ip string) (*UDP_manager, error) {
    //p, err := net.ListenPacket("ip4:1", ip)
    //if err != nil {
    //    fmt.Println(err)
    //    return nil, err
    //}

    // TODO: Separate the server UDP and client UDP connections

    ipw, err := NewIP_Writer(ip, 17) // 17 for UDP
    if err != nil {
        return nil, err
    }

    nr, err := NewNetwork_Reader()
    if err != nil {
        return nil, err
    }

    ipr, err := nr.NewIP_Reader(ip, 17) // 17 for UDP
    if err != nil {
        return nil, err;
    }

    x := &UDP_manager{
        read: ipr,
        write: ipw,
        buff: make(map[uint16](chan []byte)),
        ipAddress: ip,
    }

    go x.readAll()

    return x, nil
}

func (x *UDP_manager) readAll() {
    for {
        _, payload, err := x.read.ReadFrom()
        if err != nil {
            continue
        }
        //        fmt.Println(b)
        fmt.Println("UDP header and payload: ", payload)

        dest := (((uint16)(payload[2])) * 256) + ((uint16)(payload[3]))
        //		fmt.Println(dest)
        //		fmt.Println(payload)
        //
        //		fmt.Println(x.buff)
        c, ok := x.buff[dest]
        //fmt.Println(ok)
        payload = payload[8:]
        if ok {
            go func() {
                c <- payload
            }()
        }
    }
}

func (x *UDP_manager) NewUDP(src, dest uint16) (*UDP, error) {
    x.buff[src] = make(chan []byte)
    return &UDP{src: src, dest: dest, bytes: x.buff[src], manager: x}, nil
}

func (c *UDP) read(size int) ([]byte, error) {
    data := <- c.bytes
    if len(data) > size {
        data = data[:size]
    }
    return data, nil
}
func (c *UDP) write(x []byte) error {
    UDPHeader := []byte{
        (byte)(c.src >> 8), (byte)(c.src), // Source port in byte slice
        (byte)(c.dest >> 8), (byte)(c.dest), // Dest port in byte slice
        (byte)((8 + len(x)) >> 8), (byte)(8 + len(x)), // Length in bytes of UDP header + data
        0, 0, // Checksum
    }

    x = append(UDPHeader, x...)

    err := c.manager.write.WriteTo(x)
    if err != nil {
        fmt.Println(err)
        return err
    }
    return nil
}
func (c *UDP) close() error {
    delete(c.manager.buff, c.src)
    return nil
}
<|endoftext|>


<commit_before>package main

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

func main() {
    status()
}

func status() {
    // See https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
    // colorReset := "\033[0m"
    colorRed := "\033[31m"
    colorGreen := "\033[32m"
    // colorBlue := "\033[34m"
    colorYellow := "\033[33m"

    target := "http://127.0.0.1:19071"
    targetName := "Config server"
    resp, err := http.Get(target + "/ApplicationStatus")
    if err != nil {
        fmt.Println(colorRed + "Could not connect to", strings.ToLower(targetName), "at", target)
        fmt.Println(colorYellow + err.Error())
        return
    }
    defer resp.Body.Close()

    scanner := bufio.NewScanner(resp.Body)

    if err := scanner.Err(); err != nil {
        fmt.Println(colorRed + "Error reading data from", strings.ToLower(targetName), "at", target)
        fmt.Println(colorYellow + err.Error())
    } else if resp.StatusCode != 200 {
        fmt.Println(colorRed + targetName, "at", target, " is not handling requests")
        fmt.Println(colorYellow + "Response status", resp.StatusCode)
    } else {
        fmt.Println(colorGreen + targetName, "at", target, "is UP")
    }
}
<commit_msg>Extract print functions<commit_after>package main

import (
    "bufio"
    "fmt"
    "net/http"
    "strings"
    "time"
)

func main() {
    status()
}

func status() {
    host := "http://127.0.0.1:19071"
    path := "/ApplicationStatus"
    description := "Config server"
    //response := request(host, path, description)

    client := &http.Client{
	    Timeout: time.Second * 30,
    }
    resp, err := client.Get(host + path)
    if err != nil {
        error("Could not connect to", strings.ToLower(description), "at", host)
        detail(err.Error())
        return
    }
    defer resp.Body.Close()

    scanner := bufio.NewScanner(resp.Body)

    if err := scanner.Err(); err != nil {
        error("Error reading data from", strings.ToLower(description), "at", host)
        detail(err.Error())
    } else if resp.StatusCode != 200 {
        error(description, "at", host, "is not ready")
        detail("Response status:", resp.Status)
    } else {
        success(description, "at", host, "is ready")
    }
}

func request(host string, path string, description string) {
}

func error(messages ...string) {
    print("\033[31m", messages)
}

func success(messages ...string) {
    print("\033[32m", messages)
}

func detail(messages ...string) {
    print("\033[33m", messages)
}

func print(prefix string, messages []string) {
   fmt.Print(prefix)
    for i := 0; i < len(messages); i++ {
        fmt.Print(messages[i])
        fmt.Print(" ")
    }
    fmt.Println("")
}
<|endoftext|>


<commit_before>package api

import (
	"errors"
	"time"

	. "github.com/cloudfoundry/cli/cf/i18n"

	"github.com/cloudfoundry/cli/cf/api/authentication"
	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	"github.com/cloudfoundry/cli/cf/models"

	"github.com/cloudfoundry/noaa"
	noaa_errors "github.com/cloudfoundry/noaa/errors"
	"github.com/cloudfoundry/noaa/events"
)

type LogsNoaaRepository interface {
	GetContainerMetrics(string, []models.AppInstanceFields) ([]models.AppInstanceFields, error)
	RecentLogsFor(appGuid string) ([]*events.LogMessage, error)
	TailNoaaLogsFor(appGuid string, onConnect func(), onMessage func(*events.LogMessage)) error
	Close()
}

type logNoaaRepository struct {
	config         core_config.Reader
	consumer       NoaaConsumer
	tokenRefresher authentication.TokenRefresher
	messageQueue   *SortedMessageQueue
	onMessage      func(*events.LogMessage)
	doneChan       chan struct{}
}

var BufferTime time.Duration = 5 * time.Second

func NewLogsNoaaRepository(config core_config.Reader, consumer NoaaConsumer, tr authentication.TokenRefresher) LogsNoaaRepository {
	return &logNoaaRepository{
		config:         config,
		consumer:       consumer,
		tokenRefresher: tr,
		messageQueue:   NewSortedMessageQueue(BufferTime, time.Now),
	}
}

func (l *logNoaaRepository) Close() {
	l.consumer.Close()
	l.flushMessageQueue()
	close(l.doneChan)
}

func (l *logNoaaRepository) GetContainerMetrics(appGuid string, instances []models.AppInstanceFields) ([]models.AppInstanceFields, error) {
	metrics, err := l.consumer.GetContainerMetrics(appGuid, l.config.AccessToken())
	switch err.(type) {
	case nil: // do nothing
	case *noaa_errors.UnauthorizedError:
		l.tokenRefresher.RefreshAuthToken()
		metrics, err = l.consumer.GetContainerMetrics(appGuid, l.config.AccessToken())
	default:
		return instances, err
	}

	for _, m := range metrics {
		instances[int(*m.InstanceIndex)].MemUsage = int64(m.GetMemoryBytes())
		instances[int(*m.InstanceIndex)].CpuUsage = m.GetCpuPercentage()
		instances[int(*m.InstanceIndex)].DiskUsage = int64(m.GetDiskBytes())
	}

	return instances, nil
}

func (l *logNoaaRepository) RecentLogsFor(appGuid string) ([]*events.LogMessage, error) {
	logs, err := l.consumer.RecentLogs(appGuid, l.config.AccessToken())

	switch err.(type) {
	case nil: // do nothing
	case *noaa_errors.UnauthorizedError:
		l.tokenRefresher.RefreshAuthToken()
		logs, err = l.consumer.RecentLogs(appGuid, l.config.AccessToken())
	default:
		return logs, err
	}

	return noaa.SortRecent(logs), err
}

func (l *logNoaaRepository) TailNoaaLogsFor(appGuid string, onConnect func(), onMessage func(*events.LogMessage)) error {
	l.doneChan = make(chan struct{})
	l.onMessage = onMessage
	endpoint := l.config.DopplerEndpoint()
	if endpoint == "" {
		return errors.New(T("Loggregator endpoint missing from config file"))
	}

	l.consumer.SetOnConnectCallback(onConnect)

	logChan := make(chan *events.LogMessage)
	errChan := make(chan error)
	closeChan := make(chan struct{})
	go l.consumer.TailingLogs(appGuid, l.config.AccessToken(), logChan, errChan, closeChan)

	for {
		sendNoaaMessages(l.messageQueue, onMessage)

		select {
		case err := <-errChan:
			switch err.(type) {
			case nil: // do nothing
			case *noaa_errors.UnauthorizedError:
				if closeChan != nil {
					l.tokenRefresher.RefreshAuthToken()
					close(closeChan)
					closeChan = nil
					go l.consumer.TailingLogs(appGuid, l.config.AccessToken(), logChan, errChan, make(chan struct{}))
				} else {
					l.Close()
					return err
				}
			default:
				l.Close()
				return err
			}
		case log := <-logChan:
			l.messageQueue.PushMessage(log)
		case <-l.doneChan:
			return nil
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func sendNoaaMessages(queue *SortedMessageQueue, onMessage func(*events.LogMessage)) {
	for queue.NextTimestamp() < time.Now().UnixNano() {
		msg := queue.PopMessage()
		onMessage(msg)
	}
}

func (l *logNoaaRepository) flushMessageQueue() {
	if l.onMessage == nil {
		return
	}

	for {
		message := l.messageQueue.PopMessage()
		if message == nil {
			break
		}

		l.onMessage(message)
	}

	l.onMessage = nil
}
<commit_msg>avoid closing channel twice<commit_after>package api

import (
	"errors"
	"time"

	. "github.com/cloudfoundry/cli/cf/i18n"

	"github.com/cloudfoundry/cli/cf/api/authentication"
	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	"github.com/cloudfoundry/cli/cf/models"

	"github.com/cloudfoundry/noaa"
	noaa_errors "github.com/cloudfoundry/noaa/errors"
	"github.com/cloudfoundry/noaa/events"
)

type LogsNoaaRepository interface {
	GetContainerMetrics(string, []models.AppInstanceFields) ([]models.AppInstanceFields, error)
	RecentLogsFor(appGuid string) ([]*events.LogMessage, error)
	TailNoaaLogsFor(appGuid string, onConnect func(), onMessage func(*events.LogMessage)) error
	Close()
}

type logNoaaRepository struct {
	config         core_config.Reader
	consumer       NoaaConsumer
	tokenRefresher authentication.TokenRefresher
	messageQueue   *SortedMessageQueue
	onMessage      func(*events.LogMessage)
	doneChan       chan struct{}
	tailing        bool
}

var BufferTime time.Duration = 5 * time.Second

func NewLogsNoaaRepository(config core_config.Reader, consumer NoaaConsumer, tr authentication.TokenRefresher) LogsNoaaRepository {
	return &logNoaaRepository{
		config:         config,
		consumer:       consumer,
		tokenRefresher: tr,
		messageQueue:   NewSortedMessageQueue(BufferTime, time.Now),
	}
}

func (l *logNoaaRepository) Close() {
	l.consumer.Close()
	l.flushMessageQueue()
	if l.tailing {
		close(l.doneChan)
		l.tailing = false
	}
}

func (l *logNoaaRepository) GetContainerMetrics(appGuid string, instances []models.AppInstanceFields) ([]models.AppInstanceFields, error) {
	metrics, err := l.consumer.GetContainerMetrics(appGuid, l.config.AccessToken())
	switch err.(type) {
	case nil: // do nothing
	case *noaa_errors.UnauthorizedError:
		l.tokenRefresher.RefreshAuthToken()
		metrics, err = l.consumer.GetContainerMetrics(appGuid, l.config.AccessToken())
	default:
		return instances, err
	}

	for _, m := range metrics {
		instances[int(*m.InstanceIndex)].MemUsage = int64(m.GetMemoryBytes())
		instances[int(*m.InstanceIndex)].CpuUsage = m.GetCpuPercentage()
		instances[int(*m.InstanceIndex)].DiskUsage = int64(m.GetDiskBytes())
	}

	return instances, nil
}

func (l *logNoaaRepository) RecentLogsFor(appGuid string) ([]*events.LogMessage, error) {
	logs, err := l.consumer.RecentLogs(appGuid, l.config.AccessToken())

	switch err.(type) {
	case nil: // do nothing
	case *noaa_errors.UnauthorizedError:
		l.tokenRefresher.RefreshAuthToken()
		logs, err = l.consumer.RecentLogs(appGuid, l.config.AccessToken())
	default:
		return logs, err
	}

	return noaa.SortRecent(logs), err
}

func (l *logNoaaRepository) TailNoaaLogsFor(appGuid string, onConnect func(), onMessage func(*events.LogMessage)) error {
	l.doneChan = make(chan struct{})
	l.tailing = true
	l.onMessage = onMessage
	endpoint := l.config.DopplerEndpoint()
	if endpoint == "" {
		return errors.New(T("Loggregator endpoint missing from config file"))
	}

	l.consumer.SetOnConnectCallback(onConnect)

	logChan := make(chan *events.LogMessage)
	errChan := make(chan error)
	closeChan := make(chan struct{})
	go l.consumer.TailingLogs(appGuid, l.config.AccessToken(), logChan, errChan, closeChan)

	for {
		sendNoaaMessages(l.messageQueue, onMessage)

		select {
		case err := <-errChan:
			switch err.(type) {
			case nil: // do nothing
			case *noaa_errors.UnauthorizedError:
				if closeChan != nil {
					l.tokenRefresher.RefreshAuthToken()
					close(closeChan)
					closeChan = nil
					go l.consumer.TailingLogs(appGuid, l.config.AccessToken(), logChan, errChan, make(chan struct{}))
				} else {
					l.Close()
					return err
				}
			default:
				l.Close()
				return err
			}
		case log := <-logChan:
			l.messageQueue.PushMessage(log)
		case <-l.doneChan:
			return nil
		default:
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func sendNoaaMessages(queue *SortedMessageQueue, onMessage func(*events.LogMessage)) {
	for queue.NextTimestamp() < time.Now().UnixNano() {
		msg := queue.PopMessage()
		onMessage(msg)
	}
}

func (l *logNoaaRepository) flushMessageQueue() {
	if l.onMessage == nil {
		return
	}

	for {
		message := l.messageQueue.PopMessage()
		if message == nil {
			break
		}

		l.onMessage(message)
	}

	l.onMessage = nil
}
<|endoftext|>


<commit_before>package gothumbor

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/url"
	"strings"
)

type ThumborOptions struct {
	Width   int
	Height  int
	Smart   bool
	FitIn   bool
	Filters []string
}

func GetCryptedThumborPath(key, imageURL string, options ThumborOptions) (url string, err error) {
	var partial string
	if partial, err = GetThumborPath(imageURL, options); err != nil {
		return
	}
	hash := hmac.New(sha1.New, []byte(key))
	hash.Write([]byte(partial))
	message := hash.Sum(nil)
	url = base64.URLEncoding.EncodeToString(message)
	url = strings.Join([]string{url, partial}, "/")
	return
}

func GetThumborPath(imageURL string, options ThumborOptions) (path string, err error) {
	if path, err = getURLParts(imageURL, options); err != nil {
		return
	}
	return path, err
}

func getURLParts(imageURL string, options ThumborOptions) (urlPartial string, err error) {

	var parts []string

	partialObject, err := url.Parse(imageURL)
	if err != nil {
		return "", err
	}
	imageURL = partialObject.EscapedPath()

	if options.Height != 0 || options.Width != 0 {
		parts = append(parts, fmt.Sprintf("%dx%d", options.Width, options.Height))
	}

	if options.Smart {
		parts = append(parts, "smart")
	}

	if options.FitIn {
		parts = append(parts, "fit-in")
	}

	for _, value := range options.Filters {
		parts = append(parts, "filters:"+value)
	}

	parts = append(parts, imageURL)
	urlPartial = strings.Join(parts, "/")

	return
}
<commit_msg>naked return<commit_after>package gothumbor

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/url"
	"strings"
)

type ThumborOptions struct {
	Width   int
	Height  int
	Smart   bool
	FitIn   bool
	Filters []string
}

func GetCryptedThumborPath(key, imageURL string, options ThumborOptions) (url string, err error) {
	var partial string
	if partial, err = GetThumborPath(imageURL, options); err != nil {
		return
	}
	hash := hmac.New(sha1.New, []byte(key))
	hash.Write([]byte(partial))
	message := hash.Sum(nil)
	url = base64.URLEncoding.EncodeToString(message)
	url = strings.Join([]string{url, partial}, "/")
	return
}

func GetThumborPath(imageURL string, options ThumborOptions) (path string, err error) {
	if path, err = getURLParts(imageURL, options); err != nil {
		return
	}
	return
}

func getURLParts(imageURL string, options ThumborOptions) (urlPartial string, err error) {

	var parts []string

	partialObject, err := url.Parse(imageURL)
	if err != nil {
		return "", err
	}
	imageURL = partialObject.EscapedPath()

	if options.Height != 0 || options.Width != 0 {
		parts = append(parts, fmt.Sprintf("%dx%d", options.Width, options.Height))
	}

	if options.Smart {
		parts = append(parts, "smart")
	}

	if options.FitIn {
		parts = append(parts, "fit-in")
	}

	for _, value := range options.Filters {
		parts = append(parts, "filters:"+value)
	}

	parts = append(parts, imageURL)
	urlPartial = strings.Join(parts, "/")

	return
}
<|endoftext|>