<commit_before>// Copyright 2016 The Upspin 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 cache implements various caching strategies.
package cache // import "upspin.io/cache"

// This is mostly copied from https://github.com/golang/build/blob/master/internal/lru/cache.go

import (
	"container/list"
	"sync"
)

// EvictionNotifier is an optional interface used by LRU entries that wish to be
// notified when they are being deleted from the LRU. If implemented by the
// value of an LRU entry, OnEviction is called when it's time for that
// entry to be evicted, due to an Add. It is not called if the entry is removed
// by the LRU's Remove or RemoveOldest methods.
type EvictionNotifier interface {
	// OnEviction is called on the value of an LRU entry when it's about
	// to be evicted from the cache. This method must not call the LRU
	// cache nor block indefinitely.
	OnEviction(key interface{})
}

// LRU is a least-recently used cache, safe for concurrent access.
type LRU struct {
	maxEntries int

	mu    sync.Mutex
	ll    *list.List
	cache map[interface{}]*list.Element
}

// *entry is the type stored in each *list.Element.
type entry struct {
	key, value interface{}
}

const runEvictionNotifier = true

// NewLRU returns a new cache with the provided maximum items.
func NewLRU(maxEntries int) *LRU {
	return &LRU{
		maxEntries: maxEntries,
		ll:         list.New(),
		cache:      make(map[interface{}]*list.Element),
	}
}

// Add adds the provided key and value to the cache, evicting
// an old item if necessary.
func (c *LRU) Add(key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()

	// Already in cache?
	if ee, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ee)
		ee.Value.(*entry).value = value
		return
	}

	// Add to cache if not present
	ele := c.ll.PushFront(&entry{key, value})
	c.cache[key] = ele

	if c.ll.Len() > c.maxEntries {
		c.removeOldest(runEvictionNotifier)
	}
}

// Get fetches the key's value from the cache.
// The ok result will be true if the item was found.
func (c *LRU) Get(key interface{}) (value interface{}, ok bool) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if ele, hit := c.cache[key]; hit {
		c.ll.MoveToFront(ele)
		return ele.Value.(*entry).value, true
	}
	return
}

// RemoveOldest removes the oldest item in the cache and returns its key and
// value. If the cache is empty, the empty string and nil are returned. The
// value's EvictionNotifier if not run.
func (c *LRU) RemoveOldest() (key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.removeOldest(!runEvictionNotifier)
}

// Remove removes a key from the cache. The return value is the value that was
// removed or nil if the key was not present. The value's EvictionNotifier is
// not run by Remove.
func (c *LRU) Remove(key interface{}) interface{} {
	c.mu.Lock()
	defer c.mu.Unlock()
	if ele, found := c.cache[key]; found {
		_, value := c.remove(ele)
		return value
	}
	return nil
}

// note: must hold c.mu
func (c *LRU) removeOldest(runEvictionNotifier bool) (key, value interface{}) {
	ele := c.ll.Back()
	if ele == nil {
		return
	}
	if runEvictionNotifier {
		// If EvictionNotifier interface is implemented on the value,
		// run it.
		ent := ele.Value.(*entry)
		if notifier, ok := ent.value.(EvictionNotifier); ok {
			notifier.OnEviction(ent.key)
		}
	}
	return c.remove(ele)
}

// note: must hold c.mu
func (c *LRU) remove(ele *list.Element) (key, value interface{}) {
	c.ll.Remove(ele)
	ent := ele.Value.(*entry)
	delete(c.cache, ent.key)
	return ent.key, ent.value
}

// Len returns the number of items in the cache.
func (c *LRU) Len() int {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.ll.Len()
}

// PeekOldest peeks at the least-recently used entry, without modifying the
// cache in any way. If the cache is empty, two nils are returned.
func (c *LRU) PeekOldest() (key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ele := c.ll.Back()
	if ele == nil {
		return
	}
	ent := ele.Value.(*entry)
	return ent.key, ent.value
}

// PeekNewest peeks at the most-recently used entry, without modifying the cache
// in any way. If the cache is empty, two nils are returned.
func (c *LRU) PeekNewest() (key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ele := c.ll.Front()
	if ele == nil {
		return
	}
	ent := ele.Value.(*entry)
	return ent.key, ent.value
}

// Iterator is an iterator through the list. The iterator points to a nil
// element at the end of the list or when the list changes.
type Iterator struct {
	lru  *LRU
	this *list.Element
}

// NewIterator returns a new iterator for the LRU.
func (c *LRU) NewIterator() *Iterator {
	c.mu.Lock()
	defer c.mu.Unlock()
	return &Iterator{lru: c, this: c.ll.Front()}
}

// GetAndAdvance returns key, value, true if the current entry is valid and advances the
// iterator. Otherwise it returns nil, nil, false.
func (i *Iterator) GetAndAdvance() (interface{}, interface{}, bool) {
	i.lru.mu.Lock()
	defer i.lru.mu.Unlock()
	if i.this == nil {
		return nil, nil, false
	}
	ent := i.this.Value.(*entry)
	i.this = i.this.Next()
	return ent.key, ent.value, true
}
<commit_msg>cache: corrected typo.<commit_after>// Copyright 2016 The Upspin 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 cache implements various caching strategies.
package cache // import "upspin.io/cache"

// This is mostly copied from https://github.com/golang/build/blob/master/internal/lru/cache.go

import (
	"container/list"
	"sync"
)

// EvictionNotifier is an optional interface used by LRU entries that wish to be
// notified when they are being deleted from the LRU. If implemented by the
// value of an LRU entry, OnEviction is called when it's time for that
// entry to be evicted, due to an Add. It is not called if the entry is removed
// by the LRU's Remove or RemoveOldest methods.
type EvictionNotifier interface {
	// OnEviction is called on the value of an LRU entry when it's about
	// to be evicted from the cache. This method must not call the LRU
	// cache nor block indefinitely.
	OnEviction(key interface{})
}

// LRU is a least-recently used cache, safe for concurrent access.
type LRU struct {
	maxEntries int

	mu    sync.Mutex
	ll    *list.List
	cache map[interface{}]*list.Element
}

// *entry is the type stored in each *list.Element.
type entry struct {
	key, value interface{}
}

const runEvictionNotifier = true

// NewLRU returns a new cache with the provided maximum items.
func NewLRU(maxEntries int) *LRU {
	return &LRU{
		maxEntries: maxEntries,
		ll:         list.New(),
		cache:      make(map[interface{}]*list.Element),
	}
}

// Add adds the provided key and value to the cache, evicting
// an old item if necessary.
func (c *LRU) Add(key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()

	// Already in cache?
	if ee, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ee)
		ee.Value.(*entry).value = value
		return
	}

	// Add to cache if not present
	ele := c.ll.PushFront(&entry{key, value})
	c.cache[key] = ele

	if c.ll.Len() > c.maxEntries {
		c.removeOldest(runEvictionNotifier)
	}
}

// Get fetches the key's value from the cache.
// The ok result will be true if the item was found.
func (c *LRU) Get(key interface{}) (value interface{}, ok bool) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if ele, hit := c.cache[key]; hit {
		c.ll.MoveToFront(ele)
		return ele.Value.(*entry).value, true
	}
	return
}

// RemoveOldest removes the oldest item in the cache and returns its key and
// value. If the cache is empty, the empty string and nil are returned. The
// value's EvictionNotifier is not run.
func (c *LRU) RemoveOldest() (key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.removeOldest(!runEvictionNotifier)
}

// Remove removes a key from the cache. The return value is the value that was
// removed or nil if the key was not present. The value's EvictionNotifier is
// not run by Remove.
func (c *LRU) Remove(key interface{}) interface{} {
	c.mu.Lock()
	defer c.mu.Unlock()
	if ele, found := c.cache[key]; found {
		_, value := c.remove(ele)
		return value
	}
	return nil
}

// note: must hold c.mu
func (c *LRU) removeOldest(runEvictionNotifier bool) (key, value interface{}) {
	ele := c.ll.Back()
	if ele == nil {
		return
	}
	if runEvictionNotifier {
		// If EvictionNotifier interface is implemented on the value,
		// run it.
		ent := ele.Value.(*entry)
		if notifier, ok := ent.value.(EvictionNotifier); ok {
			notifier.OnEviction(ent.key)
		}
	}
	return c.remove(ele)
}

// note: must hold c.mu
func (c *LRU) remove(ele *list.Element) (key, value interface{}) {
	c.ll.Remove(ele)
	ent := ele.Value.(*entry)
	delete(c.cache, ent.key)
	return ent.key, ent.value
}

// Len returns the number of items in the cache.
func (c *LRU) Len() int {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.ll.Len()
}

// PeekOldest peeks at the least-recently used entry, without modifying the
// cache in any way. If the cache is empty, two nils are returned.
func (c *LRU) PeekOldest() (key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ele := c.ll.Back()
	if ele == nil {
		return
	}
	ent := ele.Value.(*entry)
	return ent.key, ent.value
}

// PeekNewest peeks at the most-recently used entry, without modifying the cache
// in any way. If the cache is empty, two nils are returned.
func (c *LRU) PeekNewest() (key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ele := c.ll.Front()
	if ele == nil {
		return
	}
	ent := ele.Value.(*entry)
	return ent.key, ent.value
}

// Iterator is an iterator through the list. The iterator points to a nil
// element at the end of the list or when the list changes.
type Iterator struct {
	lru  *LRU
	this *list.Element
}

// NewIterator returns a new iterator for the LRU.
func (c *LRU) NewIterator() *Iterator {
	c.mu.Lock()
	defer c.mu.Unlock()
	return &Iterator{lru: c, this: c.ll.Front()}
}

// GetAndAdvance returns key, value, true if the current entry is valid and advances the
// iterator. Otherwise it returns nil, nil, false.
func (i *Iterator) GetAndAdvance() (interface{}, interface{}, bool) {
	i.lru.mu.Lock()
	defer i.lru.mu.Unlock()
	if i.this == nil {
		return nil, nil, false
	}
	ent := i.this.Value.(*entry)
	i.this = i.this.Next()
	return ent.key, ent.value, true
}
<|endoftext|>


<commit_before>package collector

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	//"os"
	"regexp"
	"strconv"

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

/*
const (
	flexswitchPortsUrl = "http://localhost:8080/public/v1/state/ports"
)
*/

var (
	flexswitchPortStatsIgnoredPorts = flag.String(
		"collector.flexswitch.ignored-ports", "^$",
		"Regexp of port interfaces to ignore for flexswitch port collector.")
	flexswitchHost = flag.String(
		"collector.flexswitch.host", "localhost",
		"Hostname to use for REST query.")
	flexswitchProto = flag.String(
		"collector.flexswitch.proto", "http",
		"Protocol to use for REST query")
	flexswitchPort = flag.String(
		"collector.flexswitch.port", "8080",
		"Port to use for REST query.")
	procPortIntFieldSep = regexp.MustCompile("[ :] *")
)

type flexswitchStatsCollector struct {
	subsystem             string
	ignoredDevicesPattern *regexp.Regexp
	metricDescs           map[string]*prometheus.Desc
}

type FlexPortDetail struct {
	IntfRef                     string  `json:"IntfRef"`
	IfIndex                     float64 `json:"IfIndex"`
	Name                        string  `json:"Name"`
	OperState                   string  `json:"OperState"`
	NumUpEvents                 float64 `json:"NumUpEvents"`
	LastUpEventTime             string  `json:"LastUpEventTime"`
	NumDownEvents               float64 `json:"NumDownEvents"`
	LastDownEventTim            string  `json:"LastDownEventTim"`
	Pvid                        float64 `json:"Pvid"`
	IfInOctets                  float64 `json:"IfInOctets"`
	IfInUcastPkts               float64 `json:"IfInUcastPkts"`
	IfInDiscards                float64 `json:"IfInDiscards"`
	IfInErrors                  float64 `json:"IfInErrors"`
	IfInUnknownProtos           float64 `json:"IfInUnknownProtos"`
	IfOutOctets                 float64 `json:"IfOutOctets"`
	IfOutUcastPkts              float64 `json:"IfOutUcastPkts"`
	IfOutDiscards               float64 `json:"IfOutDiscards"`
	IfOutErrors                 float64 `json:"IfOutErrors"`
	IfEtherUnderSizePktCnt      float64 `json:"IfEtherUnderSizePktCnt"`
	IfEtherOverSizePktCnt       float64 `json:"IfEtherOverSizePktCnt"`
	IfEtherFragments            float64 `json:"IfEtherFragments"`
	IfEtherCRCAlignError        float64 `json:"IfEtherCRCAlignError"`
	IfEtherJabber               float64 `json:"IfEtherJabber"`
	IfEtherPkts                 float64 `json:"IfEtherPkts"`
	IfEtherMCPkts               float64 `json:"IfEtherMCPkts"`
	IfEtherBcastPkts            float64 `json:"IfEtherBcastPkts"`
	IfEtherPkts64OrLessOctets   float64 `json:"IfEtherPkts64OrLessOctets"`
	IfEtherPkts65To127Octets    float64 `json:"IfEtherPkts65To127Octets"`
	IfEtherPkts128To255Octets   float64 `json:"IfEtherPkts128To255Octets"`
	IfEtherPkts256To511Octets   float64 `json:"IfEtherPkts256To511Octets"`
	IfEtherPkts512To1023Octets  float64 `json:"IfEtherPkts512To1023Octets"`
	IfEtherPkts1024To1518Octets float64 `json:"IfEtherPkts1024To1518Octets"`
	ErrDisableReason            string  `json:"ErrDisableReason"`
	PresentInHW                 string  `json:"PresentInHW"`
	ConfigMode                  string  `json:"ConfigMode"`
	PRBSRxErrCnt                float64 `json:"PRBSRxErrCnt"`
}

type FlexPort struct {
	ObjectId string         `"json:"ObjectId"`
	Object   FlexPortDetail `"json:Object"`
}

type FlexPortIndex struct {
	MoreExist     bool       `json"MoreExist"`
	ObjCount      float64    `json"ObjCount"`
	CurrentMarker float64    `json"CurrentMarker"`
	NextMarker    float64    `json"NextMarker"`
	Objects       []FlexPort `json"Objects"`
}

type FlexPortStat map[float64]FlexPort

func init() {
	Factories["flexswitch"] = NewPortStatsCollector
}

func NewPortStatsCollector() (Collector, error) {
	pattern := regexp.MustCompile(*flexswitchPortStatsIgnoredPorts)
	return &flexswitchStatsCollector{
		subsystem:             "network",
		ignoredDevicesPattern: pattern,
		metricDescs:           map[string]*prometheus.Desc{},
	}, nil
}

func getFlexswitchNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
	flexswitchPortsUrl := *flexswitchProto + "://" +
		*flexswitchHost + ":" + *flexswitchPort +
		"/public/v1/state/ports"
	resp, err := http.Get(flexswitchPortsUrl)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return parseFlexSwitchStats(resp, ignore)
}

func parseFlexSwitchStats(r *http.Response, ignore *regexp.Regexp) (map[string]map[string]string, error) {
	htmlBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, fmt.Errorf("invalid http body output:", err)
	}

	var jsonBody FlexPortIndex
	err = json.Unmarshal(htmlBody, &jsonBody)
	if err != nil {
		return nil, fmt.Errorf("could not unmarshal json output:", err)
	}

	netDev := map[string]map[string]string{}

	for i := 0; i < int(jsonBody.ObjCount); i++ {
		Port := jsonBody.Objects[i].Object
		if ignore.MatchString(Port.Name) {
			log.Debugf("Ignoring device: %s", Port.Name)
			continue
		}
		netDev[Port.Name] = map[string]string{}
		// We should probably not be in the business of renaming the output
		// but I want them to be consistent with /proc/net/dev... least for
		// the ones that sync up
		netDev[Port.Name]["receive_bytes"] = strconv.FormatFloat(Port.IfInOctets, 'E', -1, 64)
		netDev[Port.Name]["transmit_bytes"] = strconv.FormatFloat(Port.IfOutOctets, 'E', -1, 64)

		netDev[Port.Name]["receive_packets"] = strconv.FormatFloat(Port.IfInUcastPkts, 'E', -1, 64)
		netDev[Port.Name]["transmit_packets"] = strconv.FormatFloat(Port.IfOutUcastPkts, 'E', -1, 64)

		netDev[Port.Name]["receive_errs"] = strconv.FormatFloat(Port.IfInErrors, 'E', -1, 64)
		netDev[Port.Name]["transmit_errs"] = strconv.FormatFloat(Port.IfOutErrors, 'E', -1, 64)

		netDev[Port.Name]["receive_drop"] = strconv.FormatFloat(Port.IfInDiscards, 'E', -1, 64)
		netDev[Port.Name]["transmit_drop"] = strconv.FormatFloat(Port.IfOutDiscards, 'E', -1, 64)

		netDev[Port.Name]["NumUpEvents"] = strconv.FormatFloat(Port.NumUpEvents, 'E', -1, 64)
		netDev[Port.Name]["NumDownEvents"] = strconv.FormatFloat(Port.NumDownEvents, 'E', -1, 64)
		netDev[Port.Name]["IfInUnknownProtos"] = strconv.FormatFloat(Port.IfInUnknownProtos, 'E', -1, 64)
		netDev[Port.Name]["IfEtherUnderSizePktCnt"] = strconv.FormatFloat(Port.IfEtherUnderSizePktCnt, 'E', -1, 64)
		netDev[Port.Name]["IfEtherOverSizePktCnt"] = strconv.FormatFloat(Port.IfEtherOverSizePktCnt, 'E', -1, 64)
		netDev[Port.Name]["IfEtherFragments"] = strconv.FormatFloat(Port.IfEtherFragments, 'E', -1, 64)
		netDev[Port.Name]["IfEtherCRCAlignError"] = strconv.FormatFloat(Port.IfEtherCRCAlignError, 'E', -1, 64)
		netDev[Port.Name]["IfEtherJabber"] = strconv.FormatFloat(Port.IfEtherJabber, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts"] = strconv.FormatFloat(Port.IfEtherPkts, 'E', -1, 64)
		netDev[Port.Name]["receive_multicast"] = strconv.FormatFloat(Port.IfEtherMCPkts, 'E', -1, 64)
		netDev[Port.Name]["IfEtherBcastPkts"] = strconv.FormatFloat(Port.IfEtherBcastPkts, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts64OrLessOctets"] = strconv.FormatFloat(Port.IfEtherPkts64OrLessOctets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts65To127Octets"] = strconv.FormatFloat(Port.IfEtherPkts65To127Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts128To255Octets"] = strconv.FormatFloat(Port.IfEtherPkts128To255Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts256To511Octets"] = strconv.FormatFloat(Port.IfEtherPkts256To511Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts512To1023Octets"] = strconv.FormatFloat(Port.IfEtherPkts512To1023Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts1024To1518Octets"] = strconv.FormatFloat(Port.IfEtherPkts1024To1518Octets, 'E', -1, 64)
	}

	return netDev, nil
}

func (c *flexswitchStatsCollector) Update(ch chan<- prometheus.Metric) (err error) {
	netDev, err := getFlexswitchNetDevStats(c.ignoredDevicesPattern)
	if err != nil {
		return fmt.Errorf("couldn't get flexswitch port stats: %s", err)
	}
	for dev, devStats := range netDev {
		for key, value := range devStats {
			desc, ok := c.metricDescs[key]
			if !ok {
				desc = prometheus.NewDesc(
					prometheus.BuildFQName(Namespace, c.subsystem, key),
					fmt.Sprintf("flexswitch network device statistic %s.", key),
					[]string{"device"},
					nil,
				)
				c.metricDescs[key] = desc
			}
			v, err := strconv.ParseFloat(value, 64)
			if err != nil {
				return fmt.Errorf("invalid value %s in port stats: %s", value, err)
			}
			ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, dev)
		}
	}
	return nil
}
<commit_msg>a little cleanup<commit_after>package collector

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"

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

var (
	flexswitchPortStatsIgnoredPorts = flag.String(
		"collector.flexswitch.ignored-ports", "^$",
		"Regexp of port interfaces to ignore for flexswitch port collector.")
	flexswitchHost = flag.String(
		"collector.flexswitch.host", "localhost",
		"Hostname to use for REST query.")
	flexswitchProto = flag.String(
		"collector.flexswitch.proto", "http",
		"Protocol to use for REST query")
	flexswitchPort = flag.String(
		"collector.flexswitch.port", "8080",
		"Port to use for REST query.")
	procPortIntFieldSep = regexp.MustCompile("[ :] *")
)

type flexswitchStatsCollector struct {
	subsystem             string
	ignoredDevicesPattern *regexp.Regexp
	metricDescs           map[string]*prometheus.Desc
}

type FlexPortDetail struct {
	IntfRef                     string  `json:"IntfRef"`
	IfIndex                     float64 `json:"IfIndex"`
	Name                        string  `json:"Name"`
	OperState                   string  `json:"OperState"`
	NumUpEvents                 float64 `json:"NumUpEvents"`
	LastUpEventTime             string  `json:"LastUpEventTime"`
	NumDownEvents               float64 `json:"NumDownEvents"`
	LastDownEventTim            string  `json:"LastDownEventTim"`
	Pvid                        float64 `json:"Pvid"`
	IfInOctets                  float64 `json:"IfInOctets"`
	IfInUcastPkts               float64 `json:"IfInUcastPkts"`
	IfInDiscards                float64 `json:"IfInDiscards"`
	IfInErrors                  float64 `json:"IfInErrors"`
	IfInUnknownProtos           float64 `json:"IfInUnknownProtos"`
	IfOutOctets                 float64 `json:"IfOutOctets"`
	IfOutUcastPkts              float64 `json:"IfOutUcastPkts"`
	IfOutDiscards               float64 `json:"IfOutDiscards"`
	IfOutErrors                 float64 `json:"IfOutErrors"`
	IfEtherUnderSizePktCnt      float64 `json:"IfEtherUnderSizePktCnt"`
	IfEtherOverSizePktCnt       float64 `json:"IfEtherOverSizePktCnt"`
	IfEtherFragments            float64 `json:"IfEtherFragments"`
	IfEtherCRCAlignError        float64 `json:"IfEtherCRCAlignError"`
	IfEtherJabber               float64 `json:"IfEtherJabber"`
	IfEtherPkts                 float64 `json:"IfEtherPkts"`
	IfEtherMCPkts               float64 `json:"IfEtherMCPkts"`
	IfEtherBcastPkts            float64 `json:"IfEtherBcastPkts"`
	IfEtherPkts64OrLessOctets   float64 `json:"IfEtherPkts64OrLessOctets"`
	IfEtherPkts65To127Octets    float64 `json:"IfEtherPkts65To127Octets"`
	IfEtherPkts128To255Octets   float64 `json:"IfEtherPkts128To255Octets"`
	IfEtherPkts256To511Octets   float64 `json:"IfEtherPkts256To511Octets"`
	IfEtherPkts512To1023Octets  float64 `json:"IfEtherPkts512To1023Octets"`
	IfEtherPkts1024To1518Octets float64 `json:"IfEtherPkts1024To1518Octets"`
	ErrDisableReason            string  `json:"ErrDisableReason"`
	PresentInHW                 string  `json:"PresentInHW"`
	ConfigMode                  string  `json:"ConfigMode"`
	PRBSRxErrCnt                float64 `json:"PRBSRxErrCnt"`
}

type FlexPort struct {
	ObjectId string         `"json:"ObjectId"`
	Object   FlexPortDetail `"json:Object"`
}

type FlexPortIndex struct {
	MoreExist     bool       `json"MoreExist"`
	ObjCount      float64    `json"ObjCount"`
	CurrentMarker float64    `json"CurrentMarker"`
	NextMarker    float64    `json"NextMarker"`
	Objects       []FlexPort `json"Objects"`
}

type FlexPortStat map[float64]FlexPort

func init() {
	Factories["flexswitch"] = NewPortStatsCollector
}

func NewPortStatsCollector() (Collector, error) {
	pattern := regexp.MustCompile(*flexswitchPortStatsIgnoredPorts)
	return &flexswitchStatsCollector{
		subsystem:             "network",
		ignoredDevicesPattern: pattern,
		metricDescs:           map[string]*prometheus.Desc{},
	}, nil
}

func getFlexswitchNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
	flexswitchPortsUrl := *flexswitchProto + "://" +
		*flexswitchHost + ":" + *flexswitchPort +
		"/public/v1/state/ports"
	resp, err := http.Get(flexswitchPortsUrl)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return parseFlexSwitchStats(resp, ignore)
}

func parseFlexSwitchStats(r *http.Response, ignore *regexp.Regexp) (map[string]map[string]string, error) {
	htmlBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, fmt.Errorf("invalid http body output:", err)
	}

	var jsonBody FlexPortIndex
	err = json.Unmarshal(htmlBody, &jsonBody)
	if err != nil {
		return nil, fmt.Errorf("could not unmarshal json output:", err)
	}

	netDev := map[string]map[string]string{}

	for i := 0; i < int(jsonBody.ObjCount); i++ {
		Port := jsonBody.Objects[i].Object
		if ignore.MatchString(Port.Name) {
			log.Debugf("Ignoring device: %s", Port.Name)
			continue
		}
		netDev[Port.Name] = map[string]string{}
		// We should probably not be in the business of renaming the output
		// but I want them to be consistent with /proc/net/dev... least for
		// the ones that sync up
		netDev[Port.Name]["receive_bytes"] = strconv.FormatFloat(Port.IfInOctets, 'E', -1, 64)
		netDev[Port.Name]["transmit_bytes"] = strconv.FormatFloat(Port.IfOutOctets, 'E', -1, 64)

		netDev[Port.Name]["receive_packets"] = strconv.FormatFloat(Port.IfInUcastPkts, 'E', -1, 64)
		netDev[Port.Name]["transmit_packets"] = strconv.FormatFloat(Port.IfOutUcastPkts, 'E', -1, 64)

		netDev[Port.Name]["receive_errs"] = strconv.FormatFloat(Port.IfInErrors, 'E', -1, 64)
		netDev[Port.Name]["transmit_errs"] = strconv.FormatFloat(Port.IfOutErrors, 'E', -1, 64)

		netDev[Port.Name]["receive_drop"] = strconv.FormatFloat(Port.IfInDiscards, 'E', -1, 64)
		netDev[Port.Name]["transmit_drop"] = strconv.FormatFloat(Port.IfOutDiscards, 'E', -1, 64)

		netDev[Port.Name]["NumUpEvents"] = strconv.FormatFloat(Port.NumUpEvents, 'E', -1, 64)
		netDev[Port.Name]["NumDownEvents"] = strconv.FormatFloat(Port.NumDownEvents, 'E', -1, 64)
		netDev[Port.Name]["IfInUnknownProtos"] = strconv.FormatFloat(Port.IfInUnknownProtos, 'E', -1, 64)
		netDev[Port.Name]["IfEtherUnderSizePktCnt"] = strconv.FormatFloat(Port.IfEtherUnderSizePktCnt, 'E', -1, 64)
		netDev[Port.Name]["IfEtherOverSizePktCnt"] = strconv.FormatFloat(Port.IfEtherOverSizePktCnt, 'E', -1, 64)
		netDev[Port.Name]["IfEtherFragments"] = strconv.FormatFloat(Port.IfEtherFragments, 'E', -1, 64)
		netDev[Port.Name]["IfEtherCRCAlignError"] = strconv.FormatFloat(Port.IfEtherCRCAlignError, 'E', -1, 64)
		netDev[Port.Name]["IfEtherJabber"] = strconv.FormatFloat(Port.IfEtherJabber, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts"] = strconv.FormatFloat(Port.IfEtherPkts, 'E', -1, 64)
		netDev[Port.Name]["receive_multicast"] = strconv.FormatFloat(Port.IfEtherMCPkts, 'E', -1, 64)
		netDev[Port.Name]["IfEtherBcastPkts"] = strconv.FormatFloat(Port.IfEtherBcastPkts, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts64OrLessOctets"] = strconv.FormatFloat(Port.IfEtherPkts64OrLessOctets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts65To127Octets"] = strconv.FormatFloat(Port.IfEtherPkts65To127Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts128To255Octets"] = strconv.FormatFloat(Port.IfEtherPkts128To255Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts256To511Octets"] = strconv.FormatFloat(Port.IfEtherPkts256To511Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts512To1023Octets"] = strconv.FormatFloat(Port.IfEtherPkts512To1023Octets, 'E', -1, 64)
		netDev[Port.Name]["IfEtherPkts1024To1518Octets"] = strconv.FormatFloat(Port.IfEtherPkts1024To1518Octets, 'E', -1, 64)
	}

	return netDev, nil
}

func (c *flexswitchStatsCollector) Update(ch chan<- prometheus.Metric) (err error) {
	netDev, err := getFlexswitchNetDevStats(c.ignoredDevicesPattern)
	if err != nil {
		return fmt.Errorf("couldn't get flexswitch port stats: %s", err)
	}
	for dev, devStats := range netDev {
		for key, value := range devStats {
			desc, ok := c.metricDescs[key]
			if !ok {
				desc = prometheus.NewDesc(
					prometheus.BuildFQName(Namespace, c.subsystem, key),
					fmt.Sprintf("flexswitch network device statistic %s.", key),
					[]string{"device"},
					nil,
				)
				c.metricDescs[key] = desc
			}
			v, err := strconv.ParseFloat(value, 64)
			if err != nil {
				return fmt.Errorf("invalid value %s in port stats: %s", value, err)
			}
			ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, dev)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package registry

// Schema1 sets the registry to serve v1 api
func Schema1(c *Config) {
	c.schema1 = true
}

// Htpasswd sets the auth method with htpasswd
func Htpasswd(c *Config) {
	c.auth = "htpasswd"
}

// Token sets the auth method to token, with the specified token url
func Token(tokenURL string) func(*Config) {
	return func(c *Config) {
		c.auth = "token"
		c.tokenURL = tokenURL
	}
}

// URL sets the registry url
func URL(registryURL string) func(*Config) {
	return func(c *Config) {
		c.registryURL = registryURL
	}
}
<commit_msg>Revert "testutil/registry: remove unused WithStdout(), WithStErr() opts"<commit_after>package registry

import "io"

// Schema1 sets the registry to serve v1 api
func Schema1(c *Config) {
	c.schema1 = true
}

// Htpasswd sets the auth method with htpasswd
func Htpasswd(c *Config) {
	c.auth = "htpasswd"
}

// Token sets the auth method to token, with the specified token url
func Token(tokenURL string) func(*Config) {
	return func(c *Config) {
		c.auth = "token"
		c.tokenURL = tokenURL
	}
}

// URL sets the registry url
func URL(registryURL string) func(*Config) {
	return func(c *Config) {
		c.registryURL = registryURL
	}
}

// WithStdout sets the stdout of the registry command to the passed in writer.
func WithStdout(w io.Writer) func(c *Config) {
	return func(c *Config) {
		c.stdout = w
	}
}

// WithStderr sets the stdout of the registry command to the passed in writer.
func WithStderr(w io.Writer) func(c *Config) {
	return func(c *Config) {
		c.stderr = w
	}
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 obcca

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"database/sql"
	"encoding/pem"
	"errors"
	"io/ioutil"
	"math/big"
	"os"
	"strconv"
	"time"

	_ "github.com/mattn/go-sqlite3"
	"golang.org/x/crypto/sha3"
	"github.com/spf13/viper"
)

// CA is the base certificate authority.
//
type CA struct {
	db *sql.DB

	path string

	priv *ecdsa.PrivateKey
	cert *x509.Certificate
	raw []byte
}

// NewCA sets up a new CA.
//
func NewCA(name string) *CA {
	ca := new(CA)
	ca.path = viper.GetString("server.rootpath")+"/"+viper.GetString("server.cadir")

	if _, err := os.Stat(ca.path); err != nil {
		Info.Println("Fresh start; creating databases, key pairs, and certificates.")

		if err := os.MkdirAll(ca.path, 0755); err != nil {
			Panic.Panicln(err)
		}
	}

	// open or create certificate database
	db, err := sql.Open("sqlite3", ca.path+"/"+name+".db")
	if err != nil {
		Panic.Panicln(err)
	}

	if err := db.Ping(); err != nil {
		Panic.Panicln(err)
	}
	if _, err := db.Exec("CREATE TABLE IF NOT EXISTS Certificates (row INTEGER PRIMARY KEY, id VARCHAR(64), timestamp INTEGER, usage INTEGER, cert BLOB, hash BLOB, kdfkey BLOB)"); err != nil {
		Panic.Panicln(err)
	}
	if _, err := db.Exec("CREATE TABLE IF NOT EXISTS Users (row INTEGER PRIMARY KEY, id VARCHAR(64), role INTEGER, token BLOB, state INTEGER, key BLOB)"); err != nil {
		Panic.Panicln(err)
	}
	ca.db = db

	// read or create signing key pair
	priv, err := ca.readCAPrivateKey(name)
	if err != nil {
		priv = ca.createCAKeyPair(name)
	}
	ca.priv = priv

	// read CA certificate, or create a self-signed CA certificate
	raw, err := ca.readCACertificate(name)
	if err != nil {
		raw = ca.createCACertificate(name, &ca.priv.PublicKey)
	}
	cert, err := x509.ParseCertificate(raw)
	if err != nil {
		Panic.Panicln(err)
	}

	ca.raw = raw
	ca.cert = cert

	return ca
}

// Close closes down the CA.
//
func (ca *CA) Close() {
	ca.db.Close()
}

func (ca *CA) createCAKeyPair(name string) *ecdsa.PrivateKey {
	Trace.Println("Creating CA key pair.")

	curve := elliptic.P384()

	priv, err := ecdsa.GenerateKey(curve, rand.Reader)
	if err == nil {
		raw, _ := x509.MarshalECPrivateKey(priv)
		cooked := pem.EncodeToMemory(
			&pem.Block{
				Type:  "ECDSA PRIVATE KEY",
				Bytes: raw,
			})
		err := ioutil.WriteFile(ca.path+"/"+name+".priv", cooked, 0644)
		if err != nil {
			Panic.Panicln(err)
		}

		raw, _ = x509.MarshalPKIXPublicKey(&priv.PublicKey)
		cooked = pem.EncodeToMemory(
			&pem.Block{
				Type:  "ECDSA PUBLIC KEY",
				Bytes: raw,
			})
		err = ioutil.WriteFile(ca.path+"/"+name+".pub", cooked, 0644)
		if err != nil {
			Panic.Panicln(err)
		}
	}
	if err != nil {
		Panic.Panicln(err)
	}

	return priv
}

func (ca *CA) readCAPrivateKey(name string) (*ecdsa.PrivateKey, error) {
	Trace.Println("Reading CA private key.")

	cooked, err := ioutil.ReadFile(ca.path + "/" + name + ".priv")
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(cooked)
	return x509.ParseECPrivateKey(block.Bytes)
}

func (ca *CA) createCACertificate(name string, pub *ecdsa.PublicKey) []byte {
	Trace.Println("Creating CA certificate.")

	raw, err := ca.newCertificate(name, pub, x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, nil)
	if err != nil {
		Panic.Panicln(err)
	}

	cooked := pem.EncodeToMemory(
		&pem.Block{
			Type:  "CERTIFICATE",
			Bytes: raw,
		})
	err = ioutil.WriteFile(ca.path+"/"+name+".cert", cooked, 0644)
	if err != nil {
		Panic.Panicln(err)
	}

	return raw
}

func (ca *CA) readCACertificate(name string) ([]byte, error) {
	Trace.Println("Reading CA certificate.")

	cooked, err := ioutil.ReadFile(ca.path+"/"+name+".cert")
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(cooked)
	return block.Bytes, nil
}

func (ca *CA) createCertificate(id string, pub interface{}, usage x509.KeyUsage, timestamp int64, kdfKey []byte, opt ...pkix.Extension) ([]byte, error) {
	Trace.Println("Creating certificate for "+id+".")

	raw, err := ca.newCertificate(id, pub, usage, opt)
	if err != nil {
		Error.Println(err)
		return nil, err
	}

	hash := sha3.New384()
	hash.Write(raw)
	if _, err = ca.db.Exec("INSERT INTO Certificates (id, timestamp, usage, cert, hash, kdfkey) VALUES (?, ?, ?, ?, ?, ?)", id, timestamp, usage, raw, hash.Sum(nil), kdfKey); err != nil {
		Error.Println(err)
	}

	return raw, err
}

func (ca *CA) newCertificate(id string, pub interface{}, usage x509.KeyUsage, ext []pkix.Extension) ([]byte, error) {
	notBefore := time.Now()
	notAfter := notBefore.Add(time.Hour * 24 * 90)

	parent := ca.cert
	isCA := parent == nil

	tmpl := x509.Certificate{
		SerialNumber: big.NewInt(1),
		Subject: pkix.Name{
			CommonName:   id,
			Organization: []string{"IBM"},
			Country:      []string{"US"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		SubjectKeyId:       []byte{1, 2, 3, 4},
		SignatureAlgorithm: x509.ECDSAWithSHA384,
		KeyUsage:           usage,

		BasicConstraintsValid: true,
		IsCA: isCA,
	}

	if len(ext) > 0 {
		tmpl.Extensions = ext
		tmpl.ExtraExtensions = ext
	}
	if isCA {
		parent = &tmpl
	}

	raw, err := x509.CreateCertificate(
		rand.Reader,
		&tmpl,
		parent,
		pub,
		ca.priv,
	)
	if isCA && err != nil {
		Panic.Panicln(err)
	}

	return raw, err
}

func (ca *CA) readCertificate(id string, usage x509.KeyUsage) ([]byte, error) {
	Trace.Println("Reading certificate for "+id+".")

	var raw []byte
	err := ca.db.QueryRow("SELECT cert FROM Certificates WHERE id=? AND usage=?", id, usage).Scan(&raw)

	return raw, err
}

func (ca *CA) readCertificate1(id string, ts int64) ([]byte, error) {
	Trace.Println("Reading certificate for "+id+".")

	var raw []byte
	err := ca.db.QueryRow("SELECT cert FROM Certificates WHERE id=? AND timestamp=?", id, ts).Scan(&raw)

	return raw, err
}

func (ca *CA) readCertificates(id string, opt ...int64) (*sql.Rows, error) {
	Trace.Println("Reading certificatess for "+id+".")

	if len(opt) > 0 && opt[0] != 0 {
		return ca.db.Query("SELECT cert, kdfkey FROM Certificates ORDER BY usage WHERE id=? AND timestamp=?", id, opt[0])
	}

	return ca.db.Query("SELECT cert, kdfkey FROM Certificates WHERE id=?", id)
}

func (ca *CA) readCertificateSets(id string, start, end int64) (*sql.Rows, error) {
	Trace.Println("Reading certificate sets for "+id+".")

	return ca.db.Query("SELECT cert, kdfKey, timestamp FROM Certificates ORDER BY timestamp WHERE id=? AND timestamp >= ? AND timestamp =< ?", id, start, end)
}

func (ca *CA) readCertificateByHash(hash []byte) ([]byte, error) {
	Trace.Println("Reading certificate for hash "+string(hash)+".")

	var raw []byte
	row := ca.db.QueryRow("SELECT cert FROM Certificates WHERE hash=?", hash)
	err := row.Scan(&raw)

	return raw, err
}

func (ca *CA) registerUser(id string, role int, opt ...string) (string, error) {
	Trace.Println("Registering user "+id+" as "+strconv.FormatInt(int64(role), 2)+".")

	var row int
	err := ca.db.QueryRow("SELECT row FROM Users WHERE id=?", id).Scan(&row)
	if err == nil {
		return "", errors.New("user is already registered")
	}

	var tok string
	if len(opt) > 0 && len(opt[0]) > 0 {
		tok = opt[0]
	} else {
		tok = randomString(12)
	}

	_, err = ca.db.Exec("INSERT INTO Users (id, role, token, state) VALUES (?, ?, ?, ?)", id, role, tok, 0)
	if err != nil {
		Error.Println(err)

	}

	return tok, err
}

func (ca *CA) deleteUser(id string) (error) {
	Trace.Println("Deleting user "+id+".")

	var row int
	err := ca.db.QueryRow("SELECT row FROM Users WHERE id=?", id).Scan(&row)
	if err == nil {
		_, err = ca.db.Exec("DELETE FROM Certificates Where id=?", id)
		if err != nil {
			Error.Println(err)
		}

		_, err = ca.db.Exec("DELETE FROM Users WHERE row=?", row)
		if err != nil {
			Error.Println(err)
		}
	}

	return err
}

func (ca *CA) readUsers(role int) (*sql.Rows, error) {
	Trace.Println("Reading users matching role "+strconv.FormatInt(int64(role), 2)+".")

	return ca.db.Query("SELECT id, role FROM Users WHERE role & ? != 0", role)
}

func (ca *CA) readToken(id string) *sql.Row {
	Trace.Println("Reading token for "+id+".")

	return ca.db.QueryRow("SELECT token, state, key FROM Users WHERE id=?", id)
}

func (ca *CA) readRole(id string) int {
	Trace.Println("Reading role for "+id+".")

	var role int
	ca.db.QueryRow("SELECT role FROM Users WHERE id=?", id).Scan(&role)

	return role
}
<commit_msg>Using BETWEEN.<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 obcca

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"database/sql"
	"encoding/pem"
	"errors"
	"io/ioutil"
	"math/big"
	"os"
	"strconv"
	"time"

	_ "github.com/mattn/go-sqlite3"
	"golang.org/x/crypto/sha3"
	"github.com/spf13/viper"
)

// CA is the base certificate authority.
//
type CA struct {
	db *sql.DB

	path string

	priv *ecdsa.PrivateKey
	cert *x509.Certificate
	raw []byte
}

// NewCA sets up a new CA.
//
func NewCA(name string) *CA {
	ca := new(CA)
	ca.path = viper.GetString("server.rootpath")+"/"+viper.GetString("server.cadir")

	if _, err := os.Stat(ca.path); err != nil {
		Info.Println("Fresh start; creating databases, key pairs, and certificates.")

		if err := os.MkdirAll(ca.path, 0755); err != nil {
			Panic.Panicln(err)
		}
	}

	// open or create certificate database
	db, err := sql.Open("sqlite3", ca.path+"/"+name+".db")
	if err != nil {
		Panic.Panicln(err)
	}

	if err := db.Ping(); err != nil {
		Panic.Panicln(err)
	}
	if _, err := db.Exec("CREATE TABLE IF NOT EXISTS Certificates (row INTEGER PRIMARY KEY, id VARCHAR(64), timestamp INTEGER, usage INTEGER, cert BLOB, hash BLOB, kdfkey BLOB)"); err != nil {
		Panic.Panicln(err)
	}
	if _, err := db.Exec("CREATE TABLE IF NOT EXISTS Users (row INTEGER PRIMARY KEY, id VARCHAR(64), role INTEGER, token BLOB, state INTEGER, key BLOB)"); err != nil {
		Panic.Panicln(err)
	}
	ca.db = db

	// read or create signing key pair
	priv, err := ca.readCAPrivateKey(name)
	if err != nil {
		priv = ca.createCAKeyPair(name)
	}
	ca.priv = priv

	// read CA certificate, or create a self-signed CA certificate
	raw, err := ca.readCACertificate(name)
	if err != nil {
		raw = ca.createCACertificate(name, &ca.priv.PublicKey)
	}
	cert, err := x509.ParseCertificate(raw)
	if err != nil {
		Panic.Panicln(err)
	}

	ca.raw = raw
	ca.cert = cert

	return ca
}

// Close closes down the CA.
//
func (ca *CA) Close() {
	ca.db.Close()
}

func (ca *CA) createCAKeyPair(name string) *ecdsa.PrivateKey {
	Trace.Println("Creating CA key pair.")

	curve := elliptic.P384()

	priv, err := ecdsa.GenerateKey(curve, rand.Reader)
	if err == nil {
		raw, _ := x509.MarshalECPrivateKey(priv)
		cooked := pem.EncodeToMemory(
			&pem.Block{
				Type:  "ECDSA PRIVATE KEY",
				Bytes: raw,
			})
		err := ioutil.WriteFile(ca.path+"/"+name+".priv", cooked, 0644)
		if err != nil {
			Panic.Panicln(err)
		}

		raw, _ = x509.MarshalPKIXPublicKey(&priv.PublicKey)
		cooked = pem.EncodeToMemory(
			&pem.Block{
				Type:  "ECDSA PUBLIC KEY",
				Bytes: raw,
			})
		err = ioutil.WriteFile(ca.path+"/"+name+".pub", cooked, 0644)
		if err != nil {
			Panic.Panicln(err)
		}
	}
	if err != nil {
		Panic.Panicln(err)
	}

	return priv
}

func (ca *CA) readCAPrivateKey(name string) (*ecdsa.PrivateKey, error) {
	Trace.Println("Reading CA private key.")

	cooked, err := ioutil.ReadFile(ca.path + "/" + name + ".priv")
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(cooked)
	return x509.ParseECPrivateKey(block.Bytes)
}

func (ca *CA) createCACertificate(name string, pub *ecdsa.PublicKey) []byte {
	Trace.Println("Creating CA certificate.")

	raw, err := ca.newCertificate(name, pub, x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, nil)
	if err != nil {
		Panic.Panicln(err)
	}

	cooked := pem.EncodeToMemory(
		&pem.Block{
			Type:  "CERTIFICATE",
			Bytes: raw,
		})
	err = ioutil.WriteFile(ca.path+"/"+name+".cert", cooked, 0644)
	if err != nil {
		Panic.Panicln(err)
	}

	return raw
}

func (ca *CA) readCACertificate(name string) ([]byte, error) {
	Trace.Println("Reading CA certificate.")

	cooked, err := ioutil.ReadFile(ca.path+"/"+name+".cert")
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(cooked)
	return block.Bytes, nil
}

func (ca *CA) createCertificate(id string, pub interface{}, usage x509.KeyUsage, timestamp int64, kdfKey []byte, opt ...pkix.Extension) ([]byte, error) {
	Trace.Println("Creating certificate for "+id+".")

	raw, err := ca.newCertificate(id, pub, usage, opt)
	if err != nil {
		Error.Println(err)
		return nil, err
	}

	hash := sha3.New384()
	hash.Write(raw)
	if _, err = ca.db.Exec("INSERT INTO Certificates (id, timestamp, usage, cert, hash, kdfkey) VALUES (?, ?, ?, ?, ?, ?)", id, timestamp, usage, raw, hash.Sum(nil), kdfKey); err != nil {
		Error.Println(err)
	}

	return raw, err
}

func (ca *CA) newCertificate(id string, pub interface{}, usage x509.KeyUsage, ext []pkix.Extension) ([]byte, error) {
	notBefore := time.Now()
	notAfter := notBefore.Add(time.Hour * 24 * 90)

	parent := ca.cert
	isCA := parent == nil

	tmpl := x509.Certificate{
		SerialNumber: big.NewInt(1),
		Subject: pkix.Name{
			CommonName:   id,
			Organization: []string{"IBM"},
			Country:      []string{"US"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		SubjectKeyId:       []byte{1, 2, 3, 4},
		SignatureAlgorithm: x509.ECDSAWithSHA384,
		KeyUsage:           usage,

		BasicConstraintsValid: true,
		IsCA: isCA,
	}

	if len(ext) > 0 {
		tmpl.Extensions = ext
		tmpl.ExtraExtensions = ext
	}
	if isCA {
		parent = &tmpl
	}

	raw, err := x509.CreateCertificate(
		rand.Reader,
		&tmpl,
		parent,
		pub,
		ca.priv,
	)
	if isCA && err != nil {
		Panic.Panicln(err)
	}

	return raw, err
}

func (ca *CA) readCertificate(id string, usage x509.KeyUsage) ([]byte, error) {
	Trace.Println("Reading certificate for "+id+".")

	var raw []byte
	err := ca.db.QueryRow("SELECT cert FROM Certificates WHERE id=? AND usage=?", id, usage).Scan(&raw)

	return raw, err
}

func (ca *CA) readCertificate1(id string, ts int64) ([]byte, error) {
	Trace.Println("Reading certificate for "+id+".")

	var raw []byte
	err := ca.db.QueryRow("SELECT cert FROM Certificates WHERE id=? AND timestamp=?", id, ts).Scan(&raw)

	return raw, err
}

func (ca *CA) readCertificates(id string, opt ...int64) (*sql.Rows, error) {
	Trace.Println("Reading certificatess for "+id+".")

	if len(opt) > 0 && opt[0] != 0 {
		return ca.db.Query("SELECT cert, kdfkey FROM Certificates ORDER BY usage WHERE id=? AND timestamp=?", id, opt[0])
	}

	return ca.db.Query("SELECT cert, kdfkey FROM Certificates WHERE id=?", id)
}

func (ca *CA) readCertificateSets(id string, start, end int64) (*sql.Rows, error) {
	Trace.Println("Reading certificate sets for "+id+".")

	return ca.db.Query("SELECT cert, kdfKey, timestamp FROM Certificates ORDER BY timestamp WHERE id=? AND timestamp BETWEEN ? AND ?", id, start, end)
}

func (ca *CA) readCertificateByHash(hash []byte) ([]byte, error) {
	Trace.Println("Reading certificate for hash "+string(hash)+".")

	var raw []byte
	row := ca.db.QueryRow("SELECT cert FROM Certificates WHERE hash=?", hash)
	err := row.Scan(&raw)

	return raw, err
}

func (ca *CA) registerUser(id string, role int, opt ...string) (string, error) {
	Trace.Println("Registering user "+id+" as "+strconv.FormatInt(int64(role), 2)+".")

	var row int
	err := ca.db.QueryRow("SELECT row FROM Users WHERE id=?", id).Scan(&row)
	if err == nil {
		return "", errors.New("user is already registered")
	}

	var tok string
	if len(opt) > 0 && len(opt[0]) > 0 {
		tok = opt[0]
	} else {
		tok = randomString(12)
	}

	_, err = ca.db.Exec("INSERT INTO Users (id, role, token, state) VALUES (?, ?, ?, ?)", id, role, tok, 0)
	if err != nil {
		Error.Println(err)

	}

	return tok, err
}

func (ca *CA) deleteUser(id string) (error) {
	Trace.Println("Deleting user "+id+".")

	var row int
	err := ca.db.QueryRow("SELECT row FROM Users WHERE id=?", id).Scan(&row)
	if err == nil {
		_, err = ca.db.Exec("DELETE FROM Certificates Where id=?", id)
		if err != nil {
			Error.Println(err)
		}

		_, err = ca.db.Exec("DELETE FROM Users WHERE row=?", row)
		if err != nil {
			Error.Println(err)
		}
	}

	return err
}

func (ca *CA) readUsers(role int) (*sql.Rows, error) {
	Trace.Println("Reading users matching role "+strconv.FormatInt(int64(role), 2)+".")

	return ca.db.Query("SELECT id, role FROM Users WHERE role & ? != 0", role)
}

func (ca *CA) readToken(id string) *sql.Row {
	Trace.Println("Reading token for "+id+".")

	return ca.db.QueryRow("SELECT token, state, key FROM Users WHERE id=?", id)
}

func (ca *CA) readRole(id string) int {
	Trace.Println("Reading role for "+id+".")

	var role int
	ca.db.QueryRow("SELECT role FROM Users WHERE id=?", id).Scan(&role)

	return role
}
<|endoftext|>


<commit_before>package runewidth

import (
	"os"
	"strings"

	"github.com/rivo/uniseg"
)

//go:generate go run script/generate.go

var (
	// EastAsianWidth will be set true if the current locale is CJK
	EastAsianWidth bool

	// StrictEmojiNeutral should be set false if handle broken fonts
	StrictEmojiNeutral bool = true

	// DefaultCondition is a condition in current locale
	DefaultCondition = &Condition{
		EastAsianWidth:     false,
		StrictEmojiNeutral: true,
	}
)

func init() {
	handleEnv()
}

func handleEnv() {
	env := os.Getenv("RUNEWIDTH_EASTASIAN")
	if env == "" {
		EastAsianWidth = IsEastAsian()
	} else {
		EastAsianWidth = env == "1"
	}
	// update DefaultCondition
	if DefaultCondition.EastAsianWidth != EastAsianWidth {
		DefaultCondition.EastAsianWidth = EastAsianWidth
		if len(DefaultCondition.combinedLut) > 0 {
			DefaultCondition.combinedLut = DefaultCondition.combinedLut[:0]
			CreateLUT()
		}
	}
}

type interval struct {
	first rune
	last  rune
}

type table []interval

func inTables(r rune, ts ...table) bool {
	for _, t := range ts {
		if inTable(r, t) {
			return true
		}
	}
	return false
}

func inTable(r rune, t table) bool {
	if r < t[0].first {
		return false
	}

	bot := 0
	top := len(t) - 1
	for top >= bot {
		mid := (bot + top) >> 1

		switch {
		case t[mid].last < r:
			bot = mid + 1
		case t[mid].first > r:
			top = mid - 1
		default:
			return true
		}
	}

	return false
}

var private = table{
	{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
}

var nonprint = table{
	{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
	{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
	{0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
	{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
}

// Condition have flag EastAsianWidth whether the current locale is CJK or not.
type Condition struct {
	combinedLut        []byte
	EastAsianWidth     bool
	StrictEmojiNeutral bool
}

// NewCondition return new instance of Condition which is current locale.
func NewCondition() *Condition {
	return &Condition{
		EastAsianWidth:     EastAsianWidth,
		StrictEmojiNeutral: StrictEmojiNeutral,
	}
}

// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func (c *Condition) RuneWidth(r rune) int {
	if r < 0 || r > 0x10FFFF {
		return 0
	}
	if len(c.combinedLut) > 0 {
		return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3
	}
	// optimized version, verified by TestRuneWidthChecksums()
	if !c.EastAsianWidth {
		switch {
		case r < 0x20:
			return 0
		case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint
			return 0
		case r < 0x300:
			return 1
		case inTable(r, narrow):
			return 1
		case inTables(r, nonprint, combining):
			return 0
		case inTable(r, doublewidth):
			return 2
		default:
			return 1
		}
	} else {
		switch {
		case inTables(r, nonprint, combining):
			return 0
		case inTable(r, narrow):
			return 1
		case inTables(r, ambiguous, doublewidth):
			return 2
		case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
			return 2
		default:
			return 1
		}
	}
}

// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation.
// This should not be called concurrently with other operations on c.
// If options in c is changed, CreateLUT should be called again.
func (c *Condition) CreateLUT() {
	const max = 0x110000
	lut := c.combinedLut
	if len(c.combinedLut) != 0 {
		// Remove so we don't use it.
		c.combinedLut = nil
	} else {
		lut = make([]byte, max/2)
	}
	for i := range lut {
		i32 := int32(i * 2)
		x0 := c.RuneWidth(i32)
		x1 := c.RuneWidth(i32 + 1)
		lut[i] = uint8(x0) | uint8(x1)<<4
	}
	c.combinedLut = lut
}

// StringWidth return width as you can see
func (c *Condition) StringWidth(s string) (width int) {
	g := uniseg.NewGraphemes(s)
	for g.Next() {
		var chWidth int
		for _, r := range g.Runes() {
			chWidth = c.RuneWidth(r)
			if chWidth > 0 {
				break // Our best guess at this point is to use the width of the first non-zero-width rune.
			}
		}
		width += chWidth
	}
	return
}

// Truncate return string truncated with w cells
func (c *Condition) Truncate(s string, w int, tail string) string {
	if c.StringWidth(s) <= w {
		return s
	}
	w -= c.StringWidth(tail)
	var width int
	pos := len(s)
	g := uniseg.NewGraphemes(s)
	for g.Next() {
		var chWidth int
		for _, r := range g.Runes() {
			chWidth = c.RuneWidth(r)
			if chWidth > 0 {
				break // See StringWidth() for details.
			}
		}
		if width+chWidth > w {
			pos, _ = g.Positions()
			break
		}
		width += chWidth
	}
	return s[:pos] + tail
}

// TruncateLeft cuts w cells from the beginning of the `s`.
func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
	if c.StringWidth(s) <= w {
		return prefix
	}

	var width int
	pos := len(s)

	g := uniseg.NewGraphemes(s)
	for g.Next() {
		var chWidth int
		for _, r := range g.Runes() {
			chWidth = c.RuneWidth(r)
			if chWidth > 0 {
				break // See StringWidth() for details.
			}
		}

		if width+chWidth <= w {
			width += chWidth

			continue
		}

		if width < w {
			_, pos = g.Positions()
			prefix += strings.Repeat(" ", w-width)
		} else {
			pos, _ = g.Positions()
		}

		break
	}

	return prefix + s[pos:]
}

// Wrap return string wrapped with w cells
func (c *Condition) Wrap(s string, w int) string {
	width := 0
	out := ""
	for _, r := range s {
		cw := c.RuneWidth(r)
		if r == '\n' {
			out += string(r)
			width = 0
			continue
		} else if width+cw > w {
			out += "\n"
			width = 0
			out += string(r)
			width += cw
			continue
		}
		out += string(r)
		width += cw
	}
	return out
}

// FillLeft return string filled in left by spaces in w cells
func (c *Condition) FillLeft(s string, w int) string {
	width := c.StringWidth(s)
	count := w - width
	if count > 0 {
		b := make([]byte, count)
		for i := range b {
			b[i] = ' '
		}
		return string(b) + s
	}
	return s
}

// FillRight return string filled in left by spaces in w cells
func (c *Condition) FillRight(s string, w int) string {
	width := c.StringWidth(s)
	count := w - width
	if count > 0 {
		b := make([]byte, count)
		for i := range b {
			b[i] = ' '
		}
		return s + string(b)
	}
	return s
}

// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func RuneWidth(r rune) int {
	return DefaultCondition.RuneWidth(r)
}

// IsAmbiguousWidth returns whether is ambiguous width or not.
func IsAmbiguousWidth(r rune) bool {
	return inTables(r, private, ambiguous)
}

// IsNeutralWidth returns whether is neutral width or not.
func IsNeutralWidth(r rune) bool {
	return inTable(r, neutral)
}

// StringWidth return width as you can see
func StringWidth(s string) (width int) {
	return DefaultCondition.StringWidth(s)
}

// Truncate return string truncated with w cells
func Truncate(s string, w int, tail string) string {
	return DefaultCondition.Truncate(s, w, tail)
}

// TruncateLeft cuts w cells from the beginning of the `s`.
func TruncateLeft(s string, w int, prefix string) string {
	return DefaultCondition.TruncateLeft(s, w, prefix)
}

// Wrap return string wrapped with w cells
func Wrap(s string, w int) string {
	return DefaultCondition.Wrap(s, w)
}

// FillLeft return string filled in left by spaces in w cells
func FillLeft(s string, w int) string {
	return DefaultCondition.FillLeft(s, w)
}

// FillRight return string filled in left by spaces in w cells
func FillRight(s string, w int) string {
	return DefaultCondition.FillRight(s, w)
}

// CreateLUT will create an in-memory lookup table of 557055 bytes for faster operation.
// This should not be called concurrently with other operations.
func CreateLUT() {
	if len(DefaultCondition.combinedLut) > 0 {
		return
	}
	DefaultCondition.CreateLUT()
}
<commit_msg>add spaces == width+chWidth-w<commit_after>package runewidth

import (
	"os"
	"strings"

	"github.com/rivo/uniseg"
)

//go:generate go run script/generate.go

var (
	// EastAsianWidth will be set true if the current locale is CJK
	EastAsianWidth bool

	// StrictEmojiNeutral should be set false if handle broken fonts
	StrictEmojiNeutral bool = true

	// DefaultCondition is a condition in current locale
	DefaultCondition = &Condition{
		EastAsianWidth:     false,
		StrictEmojiNeutral: true,
	}
)

func init() {
	handleEnv()
}

func handleEnv() {
	env := os.Getenv("RUNEWIDTH_EASTASIAN")
	if env == "" {
		EastAsianWidth = IsEastAsian()
	} else {
		EastAsianWidth = env == "1"
	}
	// update DefaultCondition
	if DefaultCondition.EastAsianWidth != EastAsianWidth {
		DefaultCondition.EastAsianWidth = EastAsianWidth
		if len(DefaultCondition.combinedLut) > 0 {
			DefaultCondition.combinedLut = DefaultCondition.combinedLut[:0]
			CreateLUT()
		}
	}
}

type interval struct {
	first rune
	last  rune
}

type table []interval

func inTables(r rune, ts ...table) bool {
	for _, t := range ts {
		if inTable(r, t) {
			return true
		}
	}
	return false
}

func inTable(r rune, t table) bool {
	if r < t[0].first {
		return false
	}

	bot := 0
	top := len(t) - 1
	for top >= bot {
		mid := (bot + top) >> 1

		switch {
		case t[mid].last < r:
			bot = mid + 1
		case t[mid].first > r:
			top = mid - 1
		default:
			return true
		}
	}

	return false
}

var private = table{
	{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
}

var nonprint = table{
	{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
	{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
	{0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
	{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
}

// Condition have flag EastAsianWidth whether the current locale is CJK or not.
type Condition struct {
	combinedLut        []byte
	EastAsianWidth     bool
	StrictEmojiNeutral bool
}

// NewCondition return new instance of Condition which is current locale.
func NewCondition() *Condition {
	return &Condition{
		EastAsianWidth:     EastAsianWidth,
		StrictEmojiNeutral: StrictEmojiNeutral,
	}
}

// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func (c *Condition) RuneWidth(r rune) int {
	if r < 0 || r > 0x10FFFF {
		return 0
	}
	if len(c.combinedLut) > 0 {
		return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3
	}
	// optimized version, verified by TestRuneWidthChecksums()
	if !c.EastAsianWidth {
		switch {
		case r < 0x20:
			return 0
		case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint
			return 0
		case r < 0x300:
			return 1
		case inTable(r, narrow):
			return 1
		case inTables(r, nonprint, combining):
			return 0
		case inTable(r, doublewidth):
			return 2
		default:
			return 1
		}
	} else {
		switch {
		case inTables(r, nonprint, combining):
			return 0
		case inTable(r, narrow):
			return 1
		case inTables(r, ambiguous, doublewidth):
			return 2
		case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
			return 2
		default:
			return 1
		}
	}
}

// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation.
// This should not be called concurrently with other operations on c.
// If options in c is changed, CreateLUT should be called again.
func (c *Condition) CreateLUT() {
	const max = 0x110000
	lut := c.combinedLut
	if len(c.combinedLut) != 0 {
		// Remove so we don't use it.
		c.combinedLut = nil
	} else {
		lut = make([]byte, max/2)
	}
	for i := range lut {
		i32 := int32(i * 2)
		x0 := c.RuneWidth(i32)
		x1 := c.RuneWidth(i32 + 1)
		lut[i] = uint8(x0) | uint8(x1)<<4
	}
	c.combinedLut = lut
}

// StringWidth return width as you can see
func (c *Condition) StringWidth(s string) (width int) {
	g := uniseg.NewGraphemes(s)
	for g.Next() {
		var chWidth int
		for _, r := range g.Runes() {
			chWidth = c.RuneWidth(r)
			if chWidth > 0 {
				break // Our best guess at this point is to use the width of the first non-zero-width rune.
			}
		}
		width += chWidth
	}
	return
}

// Truncate return string truncated with w cells
func (c *Condition) Truncate(s string, w int, tail string) string {
	if c.StringWidth(s) <= w {
		return s
	}
	w -= c.StringWidth(tail)
	var width int
	pos := len(s)
	g := uniseg.NewGraphemes(s)
	for g.Next() {
		var chWidth int
		for _, r := range g.Runes() {
			chWidth = c.RuneWidth(r)
			if chWidth > 0 {
				break // See StringWidth() for details.
			}
		}
		if width+chWidth > w {
			pos, _ = g.Positions()
			break
		}
		width += chWidth
	}
	return s[:pos] + tail
}

// TruncateLeft cuts w cells from the beginning of the `s`.
func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
	if c.StringWidth(s) <= w {
		return prefix
	}

	var width int
	pos := len(s)

	g := uniseg.NewGraphemes(s)
	for g.Next() {
		var chWidth int
		for _, r := range g.Runes() {
			chWidth = c.RuneWidth(r)
			if chWidth > 0 {
				break // See StringWidth() for details.
			}
		}

		if width+chWidth > w {
			if width < w {
				_, pos = g.Positions()
				prefix += strings.Repeat(" ", width+chWidth-w)
			} else {
				pos, _ = g.Positions()
			}

			break
		}

		width += chWidth
	}

	return prefix + s[pos:]
}

// Wrap return string wrapped with w cells
func (c *Condition) Wrap(s string, w int) string {
	width := 0
	out := ""
	for _, r := range s {
		cw := c.RuneWidth(r)
		if r == '\n' {
			out += string(r)
			width = 0
			continue
		} else if width+cw > w {
			out += "\n"
			width = 0
			out += string(r)
			width += cw
			continue
		}
		out += string(r)
		width += cw
	}
	return out
}

// FillLeft return string filled in left by spaces in w cells
func (c *Condition) FillLeft(s string, w int) string {
	width := c.StringWidth(s)
	count := w - width
	if count > 0 {
		b := make([]byte, count)
		for i := range b {
			b[i] = ' '
		}
		return string(b) + s
	}
	return s
}

// FillRight return string filled in left by spaces in w cells
func (c *Condition) FillRight(s string, w int) string {
	width := c.StringWidth(s)
	count := w - width
	if count > 0 {
		b := make([]byte, count)
		for i := range b {
			b[i] = ' '
		}
		return s + string(b)
	}
	return s
}

// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func RuneWidth(r rune) int {
	return DefaultCondition.RuneWidth(r)
}

// IsAmbiguousWidth returns whether is ambiguous width or not.
func IsAmbiguousWidth(r rune) bool {
	return inTables(r, private, ambiguous)
}

// IsNeutralWidth returns whether is neutral width or not.
func IsNeutralWidth(r rune) bool {
	return inTable(r, neutral)
}

// StringWidth return width as you can see
func StringWidth(s string) (width int) {
	return DefaultCondition.StringWidth(s)
}

// Truncate return string truncated with w cells
func Truncate(s string, w int, tail string) string {
	return DefaultCondition.Truncate(s, w, tail)
}

// TruncateLeft cuts w cells from the beginning of the `s`.
func TruncateLeft(s string, w int, prefix string) string {
	return DefaultCondition.TruncateLeft(s, w, prefix)
}

// Wrap return string wrapped with w cells
func Wrap(s string, w int) string {
	return DefaultCondition.Wrap(s, w)
}

// FillLeft return string filled in left by spaces in w cells
func FillLeft(s string, w int) string {
	return DefaultCondition.FillLeft(s, w)
}

// FillRight return string filled in left by spaces in w cells
func FillRight(s string, w int) string {
	return DefaultCondition.FillRight(s, w)
}

// CreateLUT will create an in-memory lookup table of 557055 bytes for faster operation.
// This should not be called concurrently with other operations.
func CreateLUT() {
	if len(DefaultCondition.combinedLut) > 0 {
		return
	}
	DefaultCondition.CreateLUT()
}
<|endoftext|>


<commit_before>package kcp

import (
	"container/heap"
	"sync"
	"time"
)

var updater updateHeap

func init() {
	updater.init()
	go updater.updateTask()
}

// entry contains a session update info
type entry struct {
	ts time.Time
	s  *UDPSession
}

// a global heap managed kcp.flush() caller
type updateHeap struct {
	entries  []entry
	mu       sync.Mutex
	chWakeUp chan struct{}
}

func (h *updateHeap) Len() int           { return len(h.entries) }
func (h *updateHeap) Less(i, j int) bool { return h.entries[i].ts.Before(h.entries[j].ts) }
func (h *updateHeap) Swap(i, j int) {
	h.entries[i], h.entries[j] = h.entries[j], h.entries[i]
	h.entries[i].s.updaterIdx = i
	h.entries[j].s.updaterIdx = j
}

func (h *updateHeap) Push(x interface{}) {
	h.entries = append(h.entries, x.(entry))
	n := len(h.entries)
	h.entries[n-1].s.updaterIdx = n - 1
}

func (h *updateHeap) Pop() interface{} {
	n := len(h.entries)
	x := h.entries[n-1]
	h.entries[n-1].s.updaterIdx = -1
	h.entries[n-1] = entry{} // manual set nil for GC
	h.entries = h.entries[0 : n-1]
	return x
}

func (h *updateHeap) init() {
	h.chWakeUp = make(chan struct{}, 1)
}

func (h *updateHeap) addSession(s *UDPSession) {
	h.mu.Lock()
	heap.Push(h, entry{time.Now(), s})
	h.mu.Unlock()
	h.wakeup()
}

func (h *updateHeap) removeSession(s *UDPSession) {
	h.mu.Lock()
	if s.updaterIdx != -1 {
		heap.Remove(h, s.updaterIdx)
	}
	h.mu.Unlock()
}

func (h *updateHeap) wakeup() {
	select {
	case h.chWakeUp <- struct{}{}:
	default:
	}
}

func (h *updateHeap) updateTask() {
	var timer <-chan time.Time
	for {
		select {
		case <-timer:
		case <-h.chWakeUp:
		}

		h.mu.Lock()
		hlen := h.Len()
		now := time.Now()
		for i := 0; i < hlen; i++ {
			entry := &h.entries[0]
			if now.After(entry.ts) {
				entry.ts = now.Add(entry.s.update())
				heap.Fix(h, 0)
			} else {
				break
			}
		}

		if hlen > 0 {
			timer = time.After(h.entries[0].ts.Sub(now))
		}
		h.mu.Unlock()
	}
}
<commit_msg>make the updater timing more accurate<commit_after>package kcp

import (
	"container/heap"
	"sync"
	"time"
)

var updater updateHeap

func init() {
	updater.init()
	go updater.updateTask()
}

// entry contains a session update info
type entry struct {
	ts time.Time
	s  *UDPSession
}

// a global heap managed kcp.flush() caller
type updateHeap struct {
	entries  []entry
	mu       sync.Mutex
	chWakeUp chan struct{}
}

func (h *updateHeap) Len() int           { return len(h.entries) }
func (h *updateHeap) Less(i, j int) bool { return h.entries[i].ts.Before(h.entries[j].ts) }
func (h *updateHeap) Swap(i, j int) {
	h.entries[i], h.entries[j] = h.entries[j], h.entries[i]
	h.entries[i].s.updaterIdx = i
	h.entries[j].s.updaterIdx = j
}

func (h *updateHeap) Push(x interface{}) {
	h.entries = append(h.entries, x.(entry))
	n := len(h.entries)
	h.entries[n-1].s.updaterIdx = n - 1
}

func (h *updateHeap) Pop() interface{} {
	n := len(h.entries)
	x := h.entries[n-1]
	h.entries[n-1].s.updaterIdx = -1
	h.entries[n-1] = entry{} // manual set nil for GC
	h.entries = h.entries[0 : n-1]
	return x
}

func (h *updateHeap) init() {
	h.chWakeUp = make(chan struct{}, 1)
}

func (h *updateHeap) addSession(s *UDPSession) {
	h.mu.Lock()
	heap.Push(h, entry{time.Now(), s})
	h.mu.Unlock()
	h.wakeup()
}

func (h *updateHeap) removeSession(s *UDPSession) {
	h.mu.Lock()
	if s.updaterIdx != -1 {
		heap.Remove(h, s.updaterIdx)
	}
	h.mu.Unlock()
}

func (h *updateHeap) wakeup() {
	select {
	case h.chWakeUp <- struct{}{}:
	default:
	}
}

func (h *updateHeap) updateTask() {
	var timer <-chan time.Time
	for {
		select {
		case <-timer:
		case <-h.chWakeUp:
		}

		h.mu.Lock()
		hlen := h.Len()
		for i := 0; i < hlen; i++ {
			entry := &h.entries[0]
			if time.Now().After(entry.ts) {
				interval := entry.s.update()
				entry.ts = time.Now().Add(interval)
				heap.Fix(h, 0)
			} else {
				break
			}
		}

		if hlen > 0 {
			timer = time.After(h.entries[0].ts.Sub(time.Now()))
		}
		h.mu.Unlock()
	}
}
<|endoftext|>


<commit_before>package jwt

import (
	"encoding/base64"
	"encoding/json"
	"net/http"
	"strings"
	"time"
)

// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
// You can override it to use another time value.  This is useful for testing or if your
// server uses a different time zone than your tokens.
var TimeFunc = time.Now

// Parse methods use this callback function to supply
// the key for verification.  The function receives the parsed,
// but unverified Token.  This allows you to use propries in the
// Header of the token (such as `kid`) to identify which key to use.
type Keyfunc func(*Token) (interface{}, error)

// A JWT Token.  Different fields will be used depending on whether you're
// creating or parsing/verifying a token.
type Token struct {
	Raw       string                 // The raw token.  Populated when you Parse a token
	Method    SigningMethod          // The signing method used or to be used
	Header    map[string]interface{} // The first segment of the token
	Claims    map[string]interface{} // The second segment of the token
	Signature string                 // The third segment of the token.  Populated when you Parse a token
	Valid     bool                   // Is the token valid?  Populated when you Parse/Verify a token
}

// Create a new Token.  Takes a signing method
func New(method SigningMethod) *Token {
	return &Token{
		Header: map[string]interface{}{
			"typ": "JWT",
			"alg": method.Alg(),
		},
		Claims: make(map[string]interface{}),
		Method: method,
	}
}

// Get the complete, signed token
func (t *Token) SignedString(key interface{}) (string, error) {
	var sig, sstr string
	var err error
	if sstr, err = t.SigningString(); err != nil {
		return "", err
	}
	if sig, err = t.Method.Sign(sstr, key); err != nil {
		return "", err
	}
	return strings.Join([]string{sstr, sig}, "."), nil
}

// Generate the signing string.  This is the
// most expensive part of the whole deal.  Unless you
// need this for something special, just go straight for
// the SignedString.
func (t *Token) SigningString() (string, error) {
	var err error
	parts := make([]string, 2)
	for i, _ := range parts {
		var source map[string]interface{}
		if i == 0 {
			source = t.Header
		} else {
			source = t.Claims
		}

		var jsonValue []byte
		if jsonValue, err = json.Marshal(source); err != nil {
			return "", err
		}

		parts[i] = EncodeSegment(jsonValue)
	}
	return strings.Join(parts, "."), nil
}

// Parse, validate, and return a token.
// keyFunc will receive the parsed token and should return the key for validating.
// If everything is kosher, err will be nil
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
	if strings.Contains(strings.ToLower(tokenString), "bearer") {
		return &ValidationError{err: "tokenstring should not contain bearer", Errors: ValidationErrorMalformed}
	}
	return new(Parser).Parse(tokenString, keyFunc)
}

// Try to find the token in an http.Request.
// This method will call ParseMultipartForm if there's no token in the header.
// Currently, it looks in the Authorization header as well as
// looking for an 'access_token' request parameter in req.Form.
func ParseFromRequest(req *http.Request, keyFunc Keyfunc) (token *Token, err error) {

	// Look for an Authorization header
	if ah := req.Header.Get("Authorization"); ah != "" {
		// Should be a bearer token
		if len(ah) > 6 && strings.ToUpper(ah[0:7]) == "BEARER " {
			return Parse(ah[7:], keyFunc)
		}
	}

	// Look for "access_token" parameter
	req.ParseMultipartForm(10e6)
	if tokStr := req.Form.Get("access_token"); tokStr != "" {
		return Parse(tokStr, keyFunc)
	}

	return nil, ErrNoTokenInRequest

}

// Encode JWT specific base64url encoding with padding stripped
func EncodeSegment(seg []byte) string {
	return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
}

// Decode JWT specific base64url encoding with padding stripped
func DecodeSegment(seg string) ([]byte, error) {
	if l := len(seg) % 4; l > 0 {
		seg += strings.Repeat("=", 4-l)
	}

	return base64.URLEncoding.DecodeString(seg)
}
<commit_msg>added right amount of return<commit_after>package jwt

import (
	"encoding/base64"
	"encoding/json"
	"net/http"
	"strings"
	"time"
)

// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
// You can override it to use another time value.  This is useful for testing or if your
// server uses a different time zone than your tokens.
var TimeFunc = time.Now

// Parse methods use this callback function to supply
// the key for verification.  The function receives the parsed,
// but unverified Token.  This allows you to use propries in the
// Header of the token (such as `kid`) to identify which key to use.
type Keyfunc func(*Token) (interface{}, error)

// A JWT Token.  Different fields will be used depending on whether you're
// creating or parsing/verifying a token.
type Token struct {
	Raw       string                 // The raw token.  Populated when you Parse a token
	Method    SigningMethod          // The signing method used or to be used
	Header    map[string]interface{} // The first segment of the token
	Claims    map[string]interface{} // The second segment of the token
	Signature string                 // The third segment of the token.  Populated when you Parse a token
	Valid     bool                   // Is the token valid?  Populated when you Parse/Verify a token
}

// Create a new Token.  Takes a signing method
func New(method SigningMethod) *Token {
	return &Token{
		Header: map[string]interface{}{
			"typ": "JWT",
			"alg": method.Alg(),
		},
		Claims: make(map[string]interface{}),
		Method: method,
	}
}

// Get the complete, signed token
func (t *Token) SignedString(key interface{}) (string, error) {
	var sig, sstr string
	var err error
	if sstr, err = t.SigningString(); err != nil {
		return "", err
	}
	if sig, err = t.Method.Sign(sstr, key); err != nil {
		return "", err
	}
	return strings.Join([]string{sstr, sig}, "."), nil
}

// Generate the signing string.  This is the
// most expensive part of the whole deal.  Unless you
// need this for something special, just go straight for
// the SignedString.
func (t *Token) SigningString() (string, error) {
	var err error
	parts := make([]string, 2)
	for i, _ := range parts {
		var source map[string]interface{}
		if i == 0 {
			source = t.Header
		} else {
			source = t.Claims
		}

		var jsonValue []byte
		if jsonValue, err = json.Marshal(source); err != nil {
			return "", err
		}

		parts[i] = EncodeSegment(jsonValue)
	}
	return strings.Join(parts, "."), nil
}

// Parse, validate, and return a token.
// keyFunc will receive the parsed token and should return the key for validating.
// If everything is kosher, err will be nil
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
	if strings.Contains(strings.ToLower(tokenString), "bearer") {
		return nil, &ValidationError{err: "tokenstring should not contain bearer", Errors: ValidationErrorMalformed}
	}
	return new(Parser).Parse(tokenString, keyFunc)
}

// Try to find the token in an http.Request.
// This method will call ParseMultipartForm if there's no token in the header.
// Currently, it looks in the Authorization header as well as
// looking for an 'access_token' request parameter in req.Form.
func ParseFromRequest(req *http.Request, keyFunc Keyfunc) (token *Token, err error) {

	// Look for an Authorization header
	if ah := req.Header.Get("Authorization"); ah != "" {
		// Should be a bearer token
		if len(ah) > 6 && strings.ToUpper(ah[0:7]) == "BEARER " {
			return Parse(ah[7:], keyFunc)
		}
	}

	// Look for "access_token" parameter
	req.ParseMultipartForm(10e6)
	if tokStr := req.Form.Get("access_token"); tokStr != "" {
		return Parse(tokStr, keyFunc)
	}

	return nil, ErrNoTokenInRequest

}

// Encode JWT specific base64url encoding with padding stripped
func EncodeSegment(seg []byte) string {
	return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
}

// Decode JWT specific base64url encoding with padding stripped
func DecodeSegment(seg string) ([]byte, error) {
	if l := len(seg) % 4; l > 0 {
		seg += strings.Repeat("=", 4-l)
	}

	return base64.URLEncoding.DecodeString(seg)
}
<|endoftext|>


<commit_before>package agent

import (
	"bytes"
	"fmt"
	"github.com/armon/go-metrics"
	"github.com/hashicorp/serf/serf"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"
)

const (
	windows = "windows"
)

var sanitizeTagRegexp = regexp.MustCompile(`[^A-Z0-9_]`)

// invokeEventScript will execute the given event script with the given
// event. Depending on the event, the semantics of how data are passed
// are a bit different. For all events, the SERF_EVENT environmental
// variable is the type of the event. For user events, the SERF_USER_EVENT
// environmental variable is also set, containing the name of the user
// event that was fired.
//
// In all events, data is passed in via stdin to faciliate piping. See
// the various stdin functions below for more information.
func invokeEventScript(logger *log.Logger, script string, self serf.Member, event serf.Event) error {
	defer metrics.MeasureSince([]string{"agent", "invoke", script}, time.Now())
	var output bytes.Buffer

	// Determine the shell invocation based on OS
	var shell, flag string
	if runtime.GOOS == windows {
		shell = "cmd"
		flag = "/C"
	} else {
		shell = "/bin/sh"
		flag = "-c"
	}

	cmd := exec.Command(shell, flag, script)
	cmd.Env = append(os.Environ(),
		"SERF_EVENT="+event.EventType().String(),
		"SERF_SELF_NAME="+self.Name,
		"SERF_SELF_ROLE="+self.Tags["role"],
	)
	cmd.Stderr = &output
	cmd.Stdout = &output

	// Add all the tags
	for name, val := range self.Tags {
		//http://stackoverflow.com/questions/2821043/allowed-characters-in-linux-environment-variable-names
		//(http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html for the long version)
		//says that env var names must be in [A-Z0-9_] and not start with [0-9].
		//we only care about the first part, so convert all chars not in [A-Z0-9_] to _
		sanitizedName := sanitizeTagRegexp.ReplaceAllString(strings.ToUpper(name), "_")
		tag_env := fmt.Sprintf("SERF_TAG_%s=%s", sanitizedName, val)
		cmd.Env = append(cmd.Env, tag_env)
	}

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}

	switch e := event.(type) {
	case serf.MemberEvent:
		go memberEventStdin(logger, stdin, &e)
	case serf.UserEvent:
		cmd.Env = append(cmd.Env, "SERF_USER_EVENT="+e.Name)
		cmd.Env = append(cmd.Env, fmt.Sprintf("SERF_USER_LTIME=%d", e.LTime))
		go streamPayload(logger, stdin, e.Payload)
	case *serf.Query:
		cmd.Env = append(cmd.Env, "SERF_QUERY_NAME="+e.Name)
		cmd.Env = append(cmd.Env, fmt.Sprintf("SERF_QUERY_LTIME=%d", e.LTime))
		go streamPayload(logger, stdin, e.Payload)
	default:
		return fmt.Errorf("Unknown event type: %s", event.EventType().String())
	}

	if err := cmd.Start(); err != nil {
		return err
	}

	err = cmd.Wait()
	logger.Printf("[DEBUG] agent: Event '%s' script output: %s",
		event.EventType().String(), output.String())
	if err != nil {
		return err
	}

	// If this is a query and we have output, respond
	if query, ok := event.(*serf.Query); ok && len(output.Bytes()) > 0 {
		if err := query.Respond(output.Bytes()); err != nil {
			logger.Printf("[WARN] agent: Failed to respond to query '%s': %s",
				event.String(), err)
		}
	}

	return nil
}

// eventClean cleans a value to be a parameter in an event line.
func eventClean(v string) string {
	v = strings.Replace(v, "\t", "\\t", -1)
	v = strings.Replace(v, "\n", "\\n", -1)
	return v
}

// Sends data on stdin for a member event.
//
// The format for the data is unix tool friendly, separated by whitespace
// and newlines. The structure of each line for any member event is:
// "NAME    ADDRESS    ROLE    TAGS" where the whitespace is actually tabs.
// The name and role are cleaned so that newlines and tabs are replaced
// with "\n" and "\t" respectively.
func memberEventStdin(logger *log.Logger, stdin io.WriteCloser, e *serf.MemberEvent) {
	defer stdin.Close()
	for _, member := range e.Members {
		// Format the tags as tag1=v1,tag2=v2,...
		var tagPairs []string
		for name, value := range member.Tags {
			tagPairs = append(tagPairs, fmt.Sprintf("%s=%s", name, value))
		}
		tags := strings.Join(tagPairs, ",")

		// Send the entire line
		_, err := stdin.Write([]byte(fmt.Sprintf(
			"%s\t%s\t%s\t%s\n",
			eventClean(member.Name),
			member.Addr.String(),
			eventClean(member.Tags["role"]),
			eventClean(tags))))
		if err != nil {
			return
		}
	}
}

// Sends data on stdin for an event. The stdin simply contains the
// payload (if any).
// Most shells read implementations need a newline, force it to be there
func streamPayload(logger *log.Logger, stdin io.WriteCloser, buf []byte) {
	defer stdin.Close()

	// Append a newline to payload if missing
	payload := buf
	if len(payload) > 0 && payload[len(payload)-1] != '\n' {
		payload = append(payload, '\n')
	}

	if _, err := stdin.Write(payload); err != nil {
		logger.Printf("[ERR] Error writing payload: %s", err)
		return
	}
}
<commit_msg>agent: Switch from unbounded buffer to circbuf<commit_after>package agent

import (
	"fmt"
	"github.com/armon/circbuf"
	"github.com/armon/go-metrics"
	"github.com/hashicorp/serf/serf"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"
)

const (
	windows = "windows"

	// maxBufSize limits how much data we collect from a handler.
	// This is to prevent Serf's memory from growing to an enormous
	// amount due to a faulty handler.
	maxBufSize = 8 * 1024
)

var sanitizeTagRegexp = regexp.MustCompile(`[^A-Z0-9_]`)

// invokeEventScript will execute the given event script with the given
// event. Depending on the event, the semantics of how data are passed
// are a bit different. For all events, the SERF_EVENT environmental
// variable is the type of the event. For user events, the SERF_USER_EVENT
// environmental variable is also set, containing the name of the user
// event that was fired.
//
// In all events, data is passed in via stdin to faciliate piping. See
// the various stdin functions below for more information.
func invokeEventScript(logger *log.Logger, script string, self serf.Member, event serf.Event) error {
	defer metrics.MeasureSince([]string{"agent", "invoke", script}, time.Now())
	output, _ := circbuf.NewBuffer(maxBufSize)

	// Determine the shell invocation based on OS
	var shell, flag string
	if runtime.GOOS == windows {
		shell = "cmd"
		flag = "/C"
	} else {
		shell = "/bin/sh"
		flag = "-c"
	}

	cmd := exec.Command(shell, flag, script)
	cmd.Env = append(os.Environ(),
		"SERF_EVENT="+event.EventType().String(),
		"SERF_SELF_NAME="+self.Name,
		"SERF_SELF_ROLE="+self.Tags["role"],
	)
	cmd.Stderr = output
	cmd.Stdout = output

	// Add all the tags
	for name, val := range self.Tags {
		//http://stackoverflow.com/questions/2821043/allowed-characters-in-linux-environment-variable-names
		//(http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html for the long version)
		//says that env var names must be in [A-Z0-9_] and not start with [0-9].
		//we only care about the first part, so convert all chars not in [A-Z0-9_] to _
		sanitizedName := sanitizeTagRegexp.ReplaceAllString(strings.ToUpper(name), "_")
		tag_env := fmt.Sprintf("SERF_TAG_%s=%s", sanitizedName, val)
		cmd.Env = append(cmd.Env, tag_env)
	}

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}

	switch e := event.(type) {
	case serf.MemberEvent:
		go memberEventStdin(logger, stdin, &e)
	case serf.UserEvent:
		cmd.Env = append(cmd.Env, "SERF_USER_EVENT="+e.Name)
		cmd.Env = append(cmd.Env, fmt.Sprintf("SERF_USER_LTIME=%d", e.LTime))
		go streamPayload(logger, stdin, e.Payload)
	case *serf.Query:
		cmd.Env = append(cmd.Env, "SERF_QUERY_NAME="+e.Name)
		cmd.Env = append(cmd.Env, fmt.Sprintf("SERF_QUERY_LTIME=%d", e.LTime))
		go streamPayload(logger, stdin, e.Payload)
	default:
		return fmt.Errorf("Unknown event type: %s", event.EventType().String())
	}

	if err := cmd.Start(); err != nil {
		return err
	}

	// Warn if buffer is overritten
	if output.TotalWritten() > output.Size() {
		logger.Printf("[WARN] agent: Script '%s' generated %d bytes of output, truncated to %d",
			script, output.TotalWritten(), output.Size())
	}

	err = cmd.Wait()
	logger.Printf("[DEBUG] agent: Event '%s' script output: %s",
		event.EventType().String(), output.String())
	if err != nil {
		return err
	}

	// If this is a query and we have output, respond
	if query, ok := event.(*serf.Query); ok && output.TotalWritten() > 0 {
		if err := query.Respond(output.Bytes()); err != nil {
			logger.Printf("[WARN] agent: Failed to respond to query '%s': %s",
				event.String(), err)
		}
	}

	return nil
}

// eventClean cleans a value to be a parameter in an event line.
func eventClean(v string) string {
	v = strings.Replace(v, "\t", "\\t", -1)
	v = strings.Replace(v, "\n", "\\n", -1)
	return v
}

// Sends data on stdin for a member event.
//
// The format for the data is unix tool friendly, separated by whitespace
// and newlines. The structure of each line for any member event is:
// "NAME    ADDRESS    ROLE    TAGS" where the whitespace is actually tabs.
// The name and role are cleaned so that newlines and tabs are replaced
// with "\n" and "\t" respectively.
func memberEventStdin(logger *log.Logger, stdin io.WriteCloser, e *serf.MemberEvent) {
	defer stdin.Close()
	for _, member := range e.Members {
		// Format the tags as tag1=v1,tag2=v2,...
		var tagPairs []string
		for name, value := range member.Tags {
			tagPairs = append(tagPairs, fmt.Sprintf("%s=%s", name, value))
		}
		tags := strings.Join(tagPairs, ",")

		// Send the entire line
		_, err := stdin.Write([]byte(fmt.Sprintf(
			"%s\t%s\t%s\t%s\n",
			eventClean(member.Name),
			member.Addr.String(),
			eventClean(member.Tags["role"]),
			eventClean(tags))))
		if err != nil {
			return
		}
	}
}

// Sends data on stdin for an event. The stdin simply contains the
// payload (if any).
// Most shells read implementations need a newline, force it to be there
func streamPayload(logger *log.Logger, stdin io.WriteCloser, buf []byte) {
	defer stdin.Close()

	// Append a newline to payload if missing
	payload := buf
	if len(payload) > 0 && payload[len(payload)-1] != '\n' {
		payload = append(payload, '\n')
	}

	if _, err := stdin.Write(payload); err != nil {
		logger.Printf("[ERR] Error writing payload: %s", err)
		return
	}
}
<|endoftext|>


<commit_before>package command

import (
	"testing"
)

func TestNewType_IncorrectArgsNumber(t *testing.T) {
	_, err := NewType([]string{})
	if err != ErrIncorrectArgs {
		t.Error("Parameters' absence is not allowed, error expected.")
	}

	_, err = NewType([]string{"run", "path/to/app", "smth"})
	if err != ErrIncorrectArgs {
		t.Error("Odd number of arguments is not allowed, error expected.")
	}
}

func TestNewType(t *testing.T) {
	typ, err := NewType([]string{"run", "path/to/app", "--smth", "cool"})
	if err != nil {
		t.Errorf("Error was not expected. Got %#v.", err)
	}
	if typ.params["run"] != "path/to/app" {
		t.Error("Arguments were expected to be saved as dictionary.")
	}
	if typ.action != "run" {
		t.Errorf("Action was expected to be 'run'. Instead it is '%s'.", typ.action)
	}
}

func TestRegister_IncorrectArgs(t *testing.T) {
	typ, _ := NewType([]string{"run", "path/to/app"})
	err := typ.Register(map[string]Handler{
		"handlerX": func(action string, params Data) {
			// ToDo
		},
	})
	if err != ErrIncorrectArgs {
		t.Error("Action 'run' is not a registered handler. And thus incorrect args error expected.")
	}
}

func TestRegister(t *testing.T) {
	typ, _ := NewType([]string{"run", "path/to/app"})

	val := ""
	err := typ.Register(map[string]Handler{
		"run": func(action string, params Data) {
			val = params["run"]
		},
	})
	if err != nil {
		t.Errorf("Error expected to be nil. Got %#v.", err)
	}

	if val != "path/to/app" {
		t.Error("Handler function for 'run' was expected to be called. But apparently it wasn't.")
	}
}

// expectPanic is used to make sure there was a panic in program.
// If there wasn't, this function panics with the input message.
// Use it as follows:
//	defer expectPanic("We expected panic, but didn't get it")
//	SomeFunctionThatShouldCausePanic()
func expectPanic(msg string) {
	if err := recover(); err == nil {
		panic(msg)
	}
}
<commit_msg>Better test coverage of command subpackage<commit_after>package command

import (
	"testing"
)

func TestNewType_IncorrectArgsNumber(t *testing.T) {
	_, err := NewType([]string{})
	if err != ErrIncorrectArgs {
		t.Error("Parameters' absence is not allowed, error expected.")
	}

	_, err = NewType([]string{"run", "path/to/app", "smth"})
	if err != ErrIncorrectArgs {
		t.Error("Odd number of arguments is not allowed, error expected.")
	}
}

func TestNewType(t *testing.T) {
	typ, err := NewType([]string{"run", "path/to/app", "--smth", "cool"})
	if err != nil {
		t.Errorf("Error was not expected. Got %#v.", err)
	}
	if typ.params["run"] != "path/to/app" {
		t.Error("Arguments were expected to be saved as dictionary.")
	}
	if typ.action != "run" {
		t.Errorf("Action was expected to be 'run'. Instead it is '%s'.", typ.action)
	}
}

func TestRegister_IncorrectArgs(t *testing.T) {
	typ, _ := NewType([]string{"run", "path/to/app"})
	err := typ.Register(map[string]Handler{
		"handlerX": func(action string, params Data) {
			// ToDo
		},
	})
	if err != ErrIncorrectArgs {
		t.Error("Action 'run' is not a registered handler. And thus incorrect args error expected.")
	}
}

func TestRegister(t *testing.T) {
	typ, _ := NewType([]string{"run", "path/to/app"})

	val := ""
	err := typ.Register(map[string]Handler{
		"run": func(action string, params Data) {
			val = params["run"]
		},
	})
	if err != nil {
		t.Errorf("Error expected to be nil. Got %#v.", err)
	}

	if val != "path/to/app" {
		t.Error("Handler function for 'run' was expected to be called. But apparently it wasn't.")
	}
}

func TestDefault(t *testing.T) {
	d := Data{
		"key1": "value1",
	}
	if d.Default("key1", "smth") != "value1" {
		t.Errorf("Default is expected to return value if it exists.")
	}

	if d.Default("key2", "smth") != "smth" {
		t.Errorf("Default is expected to return default value if key is not found.")
	}
}

// expectPanic is used to make sure there was a panic in program.
// If there wasn't, this function panics with the input message.
// Use it as follows:
//	defer expectPanic("We expected panic, but didn't get it")
//	SomeFunctionThatShouldCausePanic()
func expectPanic(msg string) {
	if err := recover(); err == nil {
		panic(msg)
	}
}
<|endoftext|>


<commit_before>package message

import (
	"fmt"
	"io"
)

// Errors used by implementers of the MessageSet interface.
var (
	ErrMultipleCodecs = fmt.Errorf("multiple codecs found")
	ErrNoMessages     = fmt.Errorf("no messages provided")
	ErrNilMessages    = fmt.Errorf("nil messages provided")
)

// Constants used by implementers of the MessageSet interface.
const (
	OffsetLength  = 8
	MsgSizeLength = 4
	MsgOverhead   = MsgSizeLength + OffsetLength
)

// MessageSet defines an interface for a flat Message container with a fixed
// serialization format, whether in-memory or on-disk.
//
// The following diagrams describe the MessageSet memory layout.
//
// With no compression enabled, each Message is laid out sequentially
// and preceded by a header containing its offset and size.
//
//  -----------------------------------------------------------------
//  | offset | size | message | ... | offset+N | size N | message N |
//  -----------------------------------------------------------------
//
// With compression enabled, the previous byte slice is compressed and set as
// the value of a single Message within the MemMessageSet.
//
//  -----------------------------
//  | offset+N | size | message |
//  -----------------------------
//
// The byte sizes of each of these fields are: offset: 8, size: 4, message: size
type MessageSet interface {
	io.WriterTo
	Has(msg Message) bool
	Offset(msg Message) uint64
	Get(offset, limit uint64) ([]Message, error)
	Set(offset uint64, msgs ...Message) error
	Each(offset uint64, fn func(msg Message))
}
<commit_msg>message: Use cheaper errors.New for errors<commit_after>package message

import (
	"errors"
	"io"
)

// Errors used by implementers of the MessageSet interface.
var (
	ErrMultipleCodecs = errors.New("multiple codecs found")
	ErrNoMessages     = errors.New("no messages provided")
	ErrNilMessages    = errors.New("nil messages provided")
)

// Constants used by implementers of the MessageSet interface.
const (
	OffsetLength  = 8
	MsgSizeLength = 4
	MsgOverhead   = MsgSizeLength + OffsetLength
)

// MessageSet defines an interface for a flat Message container with a fixed
// serialization format, whether in-memory or on-disk.
//
// The following diagrams describe the MessageSet memory layout.
//
// With no compression enabled, each Message is laid out sequentially
// and preceded by a header containing its offset and size.
//
//  -----------------------------------------------------------------
//  | offset | size | message | ... | offset+N | size N | message N |
//  -----------------------------------------------------------------
//
// With compression enabled, the previous byte slice is compressed and set as
// the value of a single Message within the MemMessageSet.
//
//  -----------------------------
//  | offset+N | size | message |
//  -----------------------------
//
// The byte sizes of each of these fields are: offset: 8, size: 4, message: size
type MessageSet interface {
	io.WriterTo
	Has(msg Message) bool
	Offset(msg Message) uint64
	Get(offset, limit uint64) ([]Message, error)
	Set(offset uint64, msgs ...Message) error
	Each(offset uint64, fn func(msg Message))
}
<|endoftext|>


<commit_before>package messaging

import (
	"reflect"

	"go.uber.org/zap"

	"github.com/FederationOfFathers/dashboard/db"
)

var msgApis []MsgAPI
var Logger *zap.Logger

type StreamMessage struct {
	Platform         string
	PlatformLogo     string
	PlatformColor    string
	PlatformColorInt int
	Username         string
	UserLogo         string
	URL              string
	Game             string
	Description      string
	Timestamp        string
	ThumbnailURL     string
}

// Add Messaging APIs that will be used to send messages
func AddMsgAPI(msgApi MsgAPI) {
	Logger.Info("Adding new message API", zap.String("type", reflect.TypeOf(msgApi).String()))
	msgApis = append(msgApis, msgApi)
}

type MsgAPI interface {
	PostStreamMessage(sm StreamMessage) error
	PostNewEventMessage(e *db.Event) error
	PostJoinEventMessage(e *db.Event, member string) error
	//PostMessageToChannel(channel string, message string)
}

func SendTwitchStreamMessage(sm StreamMessage) {
	postStreamMessageToAllApis(sm)
}

func SendNewEventMessage(e *db.Event) {
	for _, msgApi := range msgApis {
		err := msgApi.PostNewEventMessage(e)
		if err != nil {
			Logger.Error("unable to send event notice", zap.Any("event", e), zap.Error(err))
		}
	}
}

func SendJoinEventMessage(e *db.Event, member *db.Member) {
	for _, msgApi := range msgApis {
		err := msgApi.PostJoinEventMessage(e, member.Name)
		if err != nil {
			Logger.Error("unable to send event join message", zap.Any("event", e), zap.String("member", member.Discord), zap.Error(err))
		}
	}
}

func postStreamMessageToAllApis(sm StreamMessage) {
	Logger.Info("sending stream message", zap.String("username", sm.Username), zap.String("platform", sm.Platform))
	for _, msgApi := range msgApis {
		err := msgApi.PostStreamMessage(sm)
		if err != nil {
			Logger.Error("unable to send stream update", zap.Error(err))
		}
	}
}
<commit_msg>Add message to error<commit_after>package messaging

import (
	"reflect"

	"go.uber.org/zap"

	"github.com/FederationOfFathers/dashboard/db"
)

var msgApis []MsgAPI
var Logger *zap.Logger

type StreamMessage struct {
	Platform         string
	PlatformLogo     string
	PlatformColor    string
	PlatformColorInt int
	Username         string
	UserLogo         string
	URL              string
	Game             string
	Description      string
	Timestamp        string
	ThumbnailURL     string
}

// Add Messaging APIs that will be used to send messages
func AddMsgAPI(msgApi MsgAPI) {
	Logger.Info("Adding new message API", zap.String("type", reflect.TypeOf(msgApi).String()))
	msgApis = append(msgApis, msgApi)
}

type MsgAPI interface {
	PostStreamMessage(sm StreamMessage) error
	PostNewEventMessage(e *db.Event) error
	PostJoinEventMessage(e *db.Event, member string) error
	//PostMessageToChannel(channel string, message string)
}

func SendTwitchStreamMessage(sm StreamMessage) {
	postStreamMessageToAllApis(sm)
}

func SendNewEventMessage(e *db.Event) {
	for _, msgApi := range msgApis {
		err := msgApi.PostNewEventMessage(e)
		if err != nil {
			Logger.Error("unable to send event notice", zap.Any("event", e), zap.Error(err))
		}
	}
}

func SendJoinEventMessage(e *db.Event, member *db.Member) {
	for _, msgApi := range msgApis {
		err := msgApi.PostJoinEventMessage(e, member.Name)
		if err != nil {
			Logger.Error("unable to send event join message", zap.Any("event", e), zap.String("member", member.Discord), zap.Error(err))
		}
	}
}

func postStreamMessageToAllApis(sm StreamMessage) {
	Logger.Info("sending stream message", zap.String("username", sm.Username), zap.String("platform", sm.Platform))
	for _, msgApi := range msgApis {
		err := msgApi.PostStreamMessage(sm)
		if err != nil {
			Logger.With(zap.Any("message", sm)).Error("unable to send stream update", zap.Error(err))
		}
	}
}
<|endoftext|>