<commit_before>package server_details

import (
	"fmt"
	"net"
	"strconv"

	"github.com/hashicorp/serf/serf"
)

// Key is used in maps and for equality tests.  A key is based on endpoints.
type Key struct {
	Datacenter string
	Port       int
	AddrString string
}

// Equal compares two Key objects
func (k *Key) Equal(x *Key) bool {
	return k.Datacenter == x.Datacenter &&
		k.Port == x.Port &&
		k.AddrString == x.AddrString
}

// ServerDetails is used to return details of a consul server
type ServerDetails struct {
	Name       string
	Datacenter string
	Port       int
	Bootstrap  bool
	Expect     int
	Version    int
	Addr       net.Addr
}

// Key returns the corresponding Key
func (s *ServerDetails) Key() *Key {
	var serverAddr string
	if s.Addr != nil {
		serverAddr = s.Addr.String() + s.Addr.Network()
	}
	return &Key{
		Datacenter: s.Datacenter,
		Port:       s.Port,
		AddrString: serverAddr,
	}
}

// String returns a string representation of ServerDetails
func (s *ServerDetails) String() string {
	return fmt.Sprintf("%s (Addr: %s) (DC: %s)", s.Name, s.Addr, s.Datacenter)
}

// IsConsulServer returns true if a serf member is a consul server. Returns a
// bool and a pointer to the ServerDetails.
func IsConsulServer(m serf.Member) (bool, *ServerDetails) {
	if m.Tags["role"] != "consul" {
		return false, nil
	}

	datacenter := m.Tags["dc"]
	_, bootstrap := m.Tags["bootstrap"]

	expect := 0
	expect_str, ok := m.Tags["expect"]
	var err error
	if ok {
		expect, err = strconv.Atoi(expect_str)
		if err != nil {
			return false, nil
		}
	}

	port_str := m.Tags["port"]
	port, err := strconv.Atoi(port_str)
	if err != nil {
		return false, nil
	}

	vsn_str := m.Tags["vsn"]
	vsn, err := strconv.Atoi(vsn_str)
	if err != nil {
		return false, nil
	}

	addr := &net.TCPAddr{IP: m.Addr, Port: port}

	parts := &ServerDetails{
		Name:       m.Name,
		Datacenter: datacenter,
		Port:       port,
		Bootstrap:  bootstrap,
		Expect:     expect,
		Addr:       addr,
		Version:    vsn,
	}
	return true, parts
}
<commit_msg>Use empty string for addr in ServerDetails.String()<commit_after>package server_details

import (
	"fmt"
	"net"
	"strconv"

	"github.com/hashicorp/serf/serf"
)

// Key is used in maps and for equality tests.  A key is based on endpoints.
type Key struct {
	Datacenter string
	Port       int
	AddrString string
}

// Equal compares two Key objects
func (k *Key) Equal(x *Key) bool {
	return k.Datacenter == x.Datacenter &&
		k.Port == x.Port &&
		k.AddrString == x.AddrString
}

// ServerDetails is used to return details of a consul server
type ServerDetails struct {
	Name       string
	Datacenter string
	Port       int
	Bootstrap  bool
	Expect     int
	Version    int
	Addr       net.Addr
}

// Key returns the corresponding Key
func (s *ServerDetails) Key() *Key {
	var serverAddr string
	if s.Addr != nil {
		serverAddr = s.Addr.String() + s.Addr.Network()
	}
	return &Key{
		Datacenter: s.Datacenter,
		Port:       s.Port,
		AddrString: serverAddr,
	}
}

// String returns a string representation of ServerDetails
func (s *ServerDetails) String() string {
	var serverAddr string
	if s.Addr != nil {
		serverAddr = s.Addr.String() + s.Addr.Network()
	}

	return fmt.Sprintf("%s (Addr: %s) (DC: %s)", s.Name, serverAddr, s.Datacenter)
}

// IsConsulServer returns true if a serf member is a consul server. Returns a
// bool and a pointer to the ServerDetails.
func IsConsulServer(m serf.Member) (bool, *ServerDetails) {
	if m.Tags["role"] != "consul" {
		return false, nil
	}

	datacenter := m.Tags["dc"]
	_, bootstrap := m.Tags["bootstrap"]

	expect := 0
	expect_str, ok := m.Tags["expect"]
	var err error
	if ok {
		expect, err = strconv.Atoi(expect_str)
		if err != nil {
			return false, nil
		}
	}

	port_str := m.Tags["port"]
	port, err := strconv.Atoi(port_str)
	if err != nil {
		return false, nil
	}

	vsn_str := m.Tags["vsn"]
	vsn, err := strconv.Atoi(vsn_str)
	if err != nil {
		return false, nil
	}

	addr := &net.TCPAddr{IP: m.Addr, Port: port}

	parts := &ServerDetails{
		Name:       m.Name,
		Datacenter: datacenter,
		Port:       port,
		Bootstrap:  bootstrap,
		Expect:     expect,
		Addr:       addr,
		Version:    vsn,
	}
	return true, parts
}
<|endoftext|>


<commit_before>package scanner

import "errors"

type Scanner struct {
	Address string
	Ports   []int
}

func (scan *Scanner) AddPort(port int) {
	scan.Ports = append(scan.Ports, port)
}

func (scan *Scanner) AddPortCollection(ports []int) {
}

func (scan *Scanner) AddRange(starts int, ends int) error {
	if starts > ends {
		return errors.New("Invalid range")
	}

	for i := starts; i <= ends; i++ {
		scan.AddPort(i)
	}

	return nil
}

func (scan *Scanner) Run() (scanReport ScanReport, error error) {
	if error != nil {
		return
	}

	if len(scan.Ports) > 0 {
		scanReport, error = SpecificPorts(scan.Address, scan.Ports)
	} else {
		scanReport, error = AllOpenedPorts(scan.Address)
	}

	if error != nil {
		return
	}

	return
}
<commit_msg>Unique ports in scanner<commit_after>package scanner

import "errors"

type Scanner struct {
	Address string
	ports   []int
}

func (scan *Scanner) AddPort(port int) {
	scan.ports = appendUnique(scan.ports, port)
}

func (scan *Scanner) AddPortCollection(ports []int) {
	for _, port := range ports {
		scan.AddPort(port)
	}
}

func (scan *Scanner) AddRange(starts int, ends int) error {
	if starts > ends {
		return errors.New("Invalid range")
	}

	for i := starts; i <= ends; i++ {
		scan.AddPort(i)
	}

	return nil
}

func appendUnique(slice []int, current int) []int {
	for _, element := range slice {
		if element == current {
			return slice
		}
	}

	return append(slice, current)
}

func (scan *Scanner) Run() (scanReport ScanReport, error error) {
	if error != nil {
		return
	}

	if len(scan.ports) > 0 {
		scanReport, error = SpecificPorts(scan.Address, scan.ports)
	} else {
		scanReport, error = AllOpenedPorts(scan.Address)
	}

	if error != nil {
		return
	}

	return
}
<|endoftext|>


<commit_before>package rest

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"io"

	"net/url"

	"github.com/golang/glog"
)

type executeRequest func(req *http.Request) (resp *http.Response, err error)

type rest struct {
	executeRequest executeRequest
}

type Rest interface {
	Call(url string, values url.Values, method string, request interface{}, response interface{}, headers http.Header) error
}

func New(
	executeRequest executeRequest,
) *rest {
	r := new(rest)
	r.executeRequest = executeRequest
	return r
}

func (r *rest) Call(url string, values url.Values, method string, request interface{}, response interface{}, headers http.Header) error {
	if values != nil {
		url = fmt.Sprintf("%s?%s", url, values.Encode())
	}
	glog.V(4).Infof("rest %s to %s", method, url)
	start := time.Now()
	defer glog.V(8).Infof("create completed in %dms", time.Now().Sub(start)/time.Millisecond)
	glog.V(8).Infof("send message to %s", url)

	var body io.Reader
	if request != nil {
		content, err := json.Marshal(request)
		if err != nil {
			glog.V(2).Infof("marhal request failed: %v", err)
			return err
		}
		if glog.V(8) {
			glog.Infof("send request to %s: %s", url, string(content))
		}
		body = bytes.NewBuffer(content)
	}
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		glog.V(2).Infof("build request failed: %v", err)
		return err
	}
	req.Header.Set("ContentType", "application/json")
	for key, values := range headers {
		for _, value := range values {
			req.Header.Add(key, value)
		}
	}
	resp, err := r.executeRequest(req)
	if err != nil {
		glog.V(2).Infof("execute request failed: %v", err)
		return err
	}
	if resp.StatusCode/100 != 2 {
		glog.V(2).Infof("status %d not 2xx", resp.StatusCode)
		return fmt.Errorf("request to %s failed with status: %d", url, resp.StatusCode)
	}
	if response != nil {
		if err = json.NewDecoder(resp.Body).Decode(response); err != nil {
			glog.V(2).Infof("decode response failed: %v", err)
			return err
		}
	}
	glog.V(8).Infof("rest call successful")
	return nil
}
<commit_msg>improve log message<commit_after>package rest

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"io"

	"net/url"

	"github.com/golang/glog"
)

type executeRequest func(req *http.Request) (resp *http.Response, err error)

type rest struct {
	executeRequest executeRequest
}

type Rest interface {
	Call(url string, values url.Values, method string, request interface{}, response interface{}, headers http.Header) error
}

func New(
	executeRequest executeRequest,
) *rest {
	r := new(rest)
	r.executeRequest = executeRequest
	return r
}

func (r *rest) Call(url string, values url.Values, method string, request interface{}, response interface{}, headers http.Header) error {
	if values != nil {
		url = fmt.Sprintf("%s?%s", url, values.Encode())
	}
	glog.V(4).Infof("rest %s to %s", method, url)
	start := time.Now()
	defer glog.V(8).Infof("create completed in %dms", time.Now().Sub(start)/time.Millisecond)
	glog.V(8).Infof("send message to %s", url)

	var body io.Reader
	if request != nil {
		content, err := json.Marshal(request)
		if err != nil {
			glog.V(2).Infof("marhal request failed: %v", err)
			return err
		}
		if glog.V(8) {
			glog.Infof("send request to %s: %s", url, string(content))
		}
		body = bytes.NewBuffer(content)
	}
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		glog.V(2).Infof("build request failed: %v", err)
		return err
	}
	req.Header.Set("ContentType", "application/json")
	for key, values := range headers {
		for _, value := range values {
			req.Header.Add(key, value)
		}
	}
	resp, err := r.executeRequest(req)
	if err != nil {
		glog.V(2).Infof("execute request failed: %v", err)
		return err
	}
	if resp.StatusCode/100 != 2 {
		glog.V(2).Infof("request to %s failed with status: %d", url, resp.StatusCode)
		return fmt.Errorf("request to %s failed with status: %d", url, resp.StatusCode)
	}
	if response != nil {
		if err = json.NewDecoder(resp.Body).Decode(response); err != nil {
			glog.V(2).Infof("decode response failed: %v", err)
			return err
		}
	}
	glog.V(8).Infof("rest call successful")
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/lightninglabs/neutrino"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
	"github.com/lightningnetwork/lnd/channeldb"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
	"github.com/lightningnetwork/lnd/routing/chainview"
	"github.com/roasbeef/btcd/chaincfg/chainhash"
	"github.com/roasbeef/btcrpcclient"
	"github.com/roasbeef/btcwallet/walletdb"
)

// chainCode is an enum-like structure for keeping track of the chains currently
// supported within lnd.
type chainCode uint32

const (
	// bitcoinChain is Bitcoin's testnet chain.
	bitcoinChain chainCode = iota

	// litecoinChain is Litecoin's testnet chain.
	litecoinChain
)

// String returns a string representation of the target chainCode.
func (c chainCode) String() string {
	switch c {
	case bitcoinChain:
		return "bitcoin"
	case litecoinChain:
		return "litecoin"
	default:
		return "kekcoin"
	}
}

// chainControl couples the three primary interfaces lnd utilizes for a
// particular chain together. A single chainControl instance will exist for all
// the chains lnd is currently active on.
type chainControl struct {
	chainIO lnwallet.BlockChainIO

	feeEstimator lnwallet.FeeEstimator

	signer lnwallet.Signer

	msgSigner lnwallet.MessageSigner

	chainNotifier chainntnfs.ChainNotifier

	chainView chainview.FilteredChainView

	wallet *lnwallet.LightningWallet
}

// newChainControlFromConfig....
func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB) (*chainControl, error) {
	// Set the RPC config from the "home" chain. Multi-chain isn't yet
	// active, so we'll restrict usage to a particular chain for now.
	homeChainConfig := cfg.Bitcoin
	if registeredChains.PrimaryChain() == litecoinChain {
		homeChainConfig = cfg.Litecoin
	}
	ltndLog.Infof("Primary chain is set to: %v",
		registeredChains.PrimaryChain())

	estimator := lnwallet.StaticFeeEstimator{FeeRate: 50}
	walletConfig := &btcwallet.Config{
		PrivatePass: []byte("hello"),
		DataDir:     homeChainConfig.ChainDir,
		NetParams:   activeNetParams.Params,
	}

	cc := &chainControl{
		feeEstimator: estimator,
	}

	var (
		err error
	)

	// If spv mode is active, then we'll be using a distimnct set of
	// chainControl interfaces that interface directly with the p2p network
	// of the selected chain.
	if cfg.SpvMode.Active {
		// TODO(roasbeef): create dest for database of chain
		//  * where to place???

		dbName := filepath.Join(homeChainConfig.ChainDir, "neutrino.db")
		nodeDatabase, err := walletdb.Create("bdb", dbName)
		if err != nil {
			return nil, err
		}

		config := neutrino.Config{
			DataDir:      homeChainConfig.ChainDir,
			Database:     nodeDatabase,
			ChainParams:  *activeNetParams.Params,
			AddPeers:     cfg.SpvMode.AddPeers,
			ConnectPeers: cfg.SpvMode.ConnectPeers,
		}

		neutrino.WaitForMoreCFHeaders = time.Second * 1
		neutrino.MaxPeers = 8
		neutrino.BanDuration = 5 * time.Second
		svc, err := neutrino.NewChainService(config)
		if err != nil {
			return nil, fmt.Errorf("unable to create neutrino: %v", err)
		}
		svc.Start()

		ltndLog.Infof("WAITING!!!!!")
		m := make(chan struct{})
		<-m

		// TODO(roasbeef): return clean up func in closure to stop spvc
		// and rest?
		// defer db.Close()
		// svc.Stop

		// TODO(roasbeef): need to modify to base things off of
		// ChainService
		//walletConfig.ChainService = svc
	} else {
		// Otherwise, we'll be speaking directly via RPC to a node.
		//
		// So first we'll load btcd/ltcd's TLS cert for the RPC
		// connection. If a raw cert was specified in the config, then
		// we'll set that directly. Otherwise, we attempt to read the
		// cert from the path specified in the config.
		var rpcCert []byte
		if homeChainConfig.RawRPCCert != "" {
			rpcCert, err = hex.DecodeString(homeChainConfig.RawRPCCert)
			if err != nil {
				return nil, err
			}
		} else {
			certFile, err := os.Open(homeChainConfig.RPCCert)
			if err != nil {
				return nil, err
			}
			rpcCert, err = ioutil.ReadAll(certFile)
			if err != nil {
				return nil, err
			}
			if err := certFile.Close(); err != nil {
				return nil, err
			}
		}

		// If the specified host for the btcd/ltcd RPC server already
		// has a port specified, then we use that directly. Otherwise,
		// we assume the default port according to the selected chain
		// parameters.
		var btcdHost string
		if strings.Contains(homeChainConfig.RPCHost, ":") {
			btcdHost = homeChainConfig.RPCHost
		} else {
			btcdHost = fmt.Sprintf("%v:%v", homeChainConfig.RPCHost,
				activeNetParams.rpcPort)
		}

		btcdUser := homeChainConfig.RPCUser
		btcdPass := homeChainConfig.RPCPass

		// TODO(roasbeef): set chain service for wallet?
		walletConfig.RPCHost = btcdHost
		walletConfig.RPCUser = homeChainConfig.RPCUser
		walletConfig.RPCPass = homeChainConfig.RPCPass
		walletConfig.CACert = rpcCert

		rpcConfig := &btcrpcclient.ConnConfig{
			Host:                 btcdHost,
			Endpoint:             "ws",
			User:                 btcdUser,
			Pass:                 btcdPass,
			Certificates:         rpcCert,
			DisableTLS:           false,
			DisableConnectOnNew:  true,
			DisableAutoReconnect: false,
		}
		cc.chainNotifier, err = btcdnotify.New(rpcConfig)
		if err != nil {
			return nil, err
		}

		// Finally, we'll create an instance of the default chain view to be
		// used within the routing layer.
		cc.chainView, err = chainview.NewBtcdFilteredChainView(*rpcConfig)
		if err != nil {
			srvrLog.Errorf("unable to create chain view: %v", err)
			return nil, err
		}
	}

	wc, err := btcwallet.New(*walletConfig)
	if err != nil {
		fmt.Printf("unable to create wallet controller: %v\n", err)
		return nil, err
	}

	cc.msgSigner = wc
	cc.signer = wc
	cc.chainIO = wc

	// Create, and start the lnwallet, which handles the core payment
	// channel logic, and exposes control via proxy state machines.
	wallet, err := lnwallet.NewLightningWallet(chanDB, cc.chainNotifier, wc,
		cc.signer, cc.chainIO, cc.feeEstimator, activeNetParams.Params)
	if err != nil {
		fmt.Printf("unable to create wallet: %v\n", err)
		return nil, err
	}
	if err := wallet.Startup(); err != nil {
		fmt.Printf("unable to start wallet: %v\n", err)
		return nil, err
	}

	ltndLog.Info("LightningWallet opened")

	cc.wallet = wallet

	return cc, nil
}

var (
	// bitcoinGenesis is the genesis hash of Bitcoin's testnet chain.
	bitcoinGenesis = chainhash.Hash([chainhash.HashSize]byte{
		0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
		0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
		0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
		0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
	})

	// litecoinGenesis is the genesis hash of Litecoin's testnet4 chain.
	litecoinGenesis = chainhash.Hash([chainhash.HashSize]byte{
		0xa0, 0x29, 0x3e, 0x4e, 0xeb, 0x3d, 0xa6, 0xe6,
		0xf5, 0x6f, 0x81, 0xed, 0x59, 0x5f, 0x57, 0x88,
		0x0d, 0x1a, 0x21, 0x56, 0x9e, 0x13, 0xee, 0xfd,
		0xd9, 0x51, 0x28, 0x4b, 0x5a, 0x62, 0x66, 0x49,
	})

	// chainMap is a simple index that maps a chain's genesis hash to the
	// chainCode enum for that chain.
	chainMap = map[chainhash.Hash]chainCode{
		bitcoinGenesis:  bitcoinChain,
		litecoinGenesis: litecoinChain,
	}

	// reverseChainMap is the inverse of the chainMap above: it maps the
	// chain enum for a chain to its genesis hash.
	reverseChainMap = map[chainCode]chainhash.Hash{
		bitcoinChain:  bitcoinGenesis,
		litecoinChain: litecoinGenesis,
	}
)

// chainRegistry keeps track of the current chains
type chainRegistry struct {
	sync.RWMutex

	activeChains map[chainCode]*chainControl
	netParams    map[chainCode]*bitcoinNetParams

	primaryChain chainCode
}

// newChainRegistry creates a new chainRegistry.
func newChainRegistry() *chainRegistry {
	return &chainRegistry{
		activeChains: make(map[chainCode]*chainControl),
		netParams:    make(map[chainCode]*bitcoinNetParams),
	}
}

// RegisterChain assigns an active chainControl instance to a target chain
// identified by its chainCode.
func (c *chainRegistry) RegisterChain(newChain chainCode, cc *chainControl) {
	c.Lock()
	c.activeChains[newChain] = cc
	c.Unlock()
}

// LookupChain attempts to lookup an active chainControl instance for the
// target chain.
func (c *chainRegistry) LookupChain(targetChain chainCode) (*chainControl, bool) {
	c.RLock()
	cc, ok := c.activeChains[targetChain]
	c.RUnlock()
	return cc, ok
}

// LookupChainByHash attempts to look up an active chainControl which
// corresponds to the passed genesis hash.
func (c *chainRegistry) LookupChainByHash(chainHash chainhash.Hash) (*chainControl, bool) {
	c.RLock()
	defer c.RUnlock()

	targetChain, ok := chainMap[chainHash]
	if !ok {
		return nil, ok
	}

	cc, ok := c.activeChains[targetChain]
	return cc, ok
}

// RegisterPrimaryChain sets a target chain as the "home chain" for lnd.
func (c *chainRegistry) RegisterPrimaryChain(cc chainCode) {
	c.Lock()
	defer c.Unlock()

	c.primaryChain = cc
}

// PrimaryChain returns the primary chain for this running lnd instance. The
// primary chain is considered the "home base" while the other registered
// chains are treated as secondary chains.
func (c *chainRegistry) PrimaryChain() chainCode {
	c.RLock()
	defer c.RUnlock()

	return c.primaryChain
}

// ActiveChains returns the total number of active chains.
func (c *chainRegistry) ActiveChains() []chainCode {
	c.RLock()
	defer c.RUnlock()

	chains := make([]chainCode, 0, len(c.activeChains))
	for activeChain := range c.activeChains {
		chains = append(chains, activeChain)
	}

	return chains
}

// NumActiveChains returns the total number of active chains.
func (c *chainRegistry) NumActiveChains() uint32 {
	c.RLock()
	defer c.RUnlock()

	return uint32(len(c.activeChains))
}
<commit_msg>chainregistry: create neutrino DB in correct directory<commit_after>package main

import (
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/lightninglabs/neutrino"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
	"github.com/lightningnetwork/lnd/channeldb"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
	"github.com/lightningnetwork/lnd/routing/chainview"
	"github.com/roasbeef/btcd/chaincfg/chainhash"
	"github.com/roasbeef/btcrpcclient"
	"github.com/roasbeef/btcwallet/walletdb"
)

// chainCode is an enum-like structure for keeping track of the chains currently
// supported within lnd.
type chainCode uint32

const (
	// bitcoinChain is Bitcoin's testnet chain.
	bitcoinChain chainCode = iota

	// litecoinChain is Litecoin's testnet chain.
	litecoinChain
)

// String returns a string representation of the target chainCode.
func (c chainCode) String() string {
	switch c {
	case bitcoinChain:
		return "bitcoin"
	case litecoinChain:
		return "litecoin"
	default:
		return "kekcoin"
	}
}

// chainControl couples the three primary interfaces lnd utilizes for a
// particular chain together. A single chainControl instance will exist for all
// the chains lnd is currently active on.
type chainControl struct {
	chainIO lnwallet.BlockChainIO

	feeEstimator lnwallet.FeeEstimator

	signer lnwallet.Signer

	msgSigner lnwallet.MessageSigner

	chainNotifier chainntnfs.ChainNotifier

	chainView chainview.FilteredChainView

	wallet *lnwallet.LightningWallet
}

// newChainControlFromConfig....
func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB) (*chainControl, error) {
	// Set the RPC config from the "home" chain. Multi-chain isn't yet
	// active, so we'll restrict usage to a particular chain for now.
	homeChainConfig := cfg.Bitcoin
	if registeredChains.PrimaryChain() == litecoinChain {
		homeChainConfig = cfg.Litecoin
	}
	ltndLog.Infof("Primary chain is set to: %v",
		registeredChains.PrimaryChain())

	estimator := lnwallet.StaticFeeEstimator{FeeRate: 50}
	walletConfig := &btcwallet.Config{
		PrivatePass: []byte("hello"),
		DataDir:     homeChainConfig.ChainDir,
		NetParams:   activeNetParams.Params,
	}

	cc := &chainControl{
		feeEstimator: estimator,
	}

	var (
		err error
	)

	// If spv mode is active, then we'll be using a distimnct set of
	// chainControl interfaces that interface directly with the p2p network
	// of the selected chain.
	if cfg.SpvMode.Active {
		// TODO(roasbeef): create dest for database of chain
		//  * where to place???

		dbName := filepath.Join(cfg.DataDir, "neutrino.db")
		nodeDatabase, err := walletdb.Create("bdb", dbName)
		if err != nil {
			return nil, err
		}

		config := neutrino.Config{
			DataDir:      homeChainConfig.ChainDir,
			Database:     nodeDatabase,
			ChainParams:  *activeNetParams.Params,
			AddPeers:     cfg.SpvMode.AddPeers,
			ConnectPeers: cfg.SpvMode.ConnectPeers,
		}

		neutrino.WaitForMoreCFHeaders = time.Second * 1
		neutrino.MaxPeers = 8
		neutrino.BanDuration = 5 * time.Second
		svc, err := neutrino.NewChainService(config)
		if err != nil {
			return nil, fmt.Errorf("unable to create neutrino: %v", err)
		}
		svc.Start()

		ltndLog.Infof("WAITING!!!!!")
		m := make(chan struct{})
		<-m

		// TODO(roasbeef): return clean up func in closure to stop spvc
		// and rest?
		// defer db.Close()
		// svc.Stop

		// TODO(roasbeef): need to modify to base things off of
		// ChainService
		//walletConfig.ChainService = svc
	} else {
		// Otherwise, we'll be speaking directly via RPC to a node.
		//
		// So first we'll load btcd/ltcd's TLS cert for the RPC
		// connection. If a raw cert was specified in the config, then
		// we'll set that directly. Otherwise, we attempt to read the
		// cert from the path specified in the config.
		var rpcCert []byte
		if homeChainConfig.RawRPCCert != "" {
			rpcCert, err = hex.DecodeString(homeChainConfig.RawRPCCert)
			if err != nil {
				return nil, err
			}
		} else {
			certFile, err := os.Open(homeChainConfig.RPCCert)
			if err != nil {
				return nil, err
			}
			rpcCert, err = ioutil.ReadAll(certFile)
			if err != nil {
				return nil, err
			}
			if err := certFile.Close(); err != nil {
				return nil, err
			}
		}

		// If the specified host for the btcd/ltcd RPC server already
		// has a port specified, then we use that directly. Otherwise,
		// we assume the default port according to the selected chain
		// parameters.
		var btcdHost string
		if strings.Contains(homeChainConfig.RPCHost, ":") {
			btcdHost = homeChainConfig.RPCHost
		} else {
			btcdHost = fmt.Sprintf("%v:%v", homeChainConfig.RPCHost,
				activeNetParams.rpcPort)
		}

		btcdUser := homeChainConfig.RPCUser
		btcdPass := homeChainConfig.RPCPass

		// TODO(roasbeef): set chain service for wallet?
		walletConfig.RPCHost = btcdHost
		walletConfig.RPCUser = homeChainConfig.RPCUser
		walletConfig.RPCPass = homeChainConfig.RPCPass
		walletConfig.CACert = rpcCert

		rpcConfig := &btcrpcclient.ConnConfig{
			Host:                 btcdHost,
			Endpoint:             "ws",
			User:                 btcdUser,
			Pass:                 btcdPass,
			Certificates:         rpcCert,
			DisableTLS:           false,
			DisableConnectOnNew:  true,
			DisableAutoReconnect: false,
		}
		cc.chainNotifier, err = btcdnotify.New(rpcConfig)
		if err != nil {
			return nil, err
		}

		// Finally, we'll create an instance of the default chain view to be
		// used within the routing layer.
		cc.chainView, err = chainview.NewBtcdFilteredChainView(*rpcConfig)
		if err != nil {
			srvrLog.Errorf("unable to create chain view: %v", err)
			return nil, err
		}
	}

	wc, err := btcwallet.New(*walletConfig)
	if err != nil {
		fmt.Printf("unable to create wallet controller: %v\n", err)
		return nil, err
	}

	cc.msgSigner = wc
	cc.signer = wc
	cc.chainIO = wc

	// Create, and start the lnwallet, which handles the core payment
	// channel logic, and exposes control via proxy state machines.
	wallet, err := lnwallet.NewLightningWallet(chanDB, cc.chainNotifier, wc,
		cc.signer, cc.chainIO, cc.feeEstimator, activeNetParams.Params)
	if err != nil {
		fmt.Printf("unable to create wallet: %v\n", err)
		return nil, err
	}
	if err := wallet.Startup(); err != nil {
		fmt.Printf("unable to start wallet: %v\n", err)
		return nil, err
	}

	ltndLog.Info("LightningWallet opened")

	cc.wallet = wallet

	return cc, nil
}

var (
	// bitcoinGenesis is the genesis hash of Bitcoin's testnet chain.
	bitcoinGenesis = chainhash.Hash([chainhash.HashSize]byte{
		0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
		0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
		0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
		0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
	})

	// litecoinGenesis is the genesis hash of Litecoin's testnet4 chain.
	litecoinGenesis = chainhash.Hash([chainhash.HashSize]byte{
		0xa0, 0x29, 0x3e, 0x4e, 0xeb, 0x3d, 0xa6, 0xe6,
		0xf5, 0x6f, 0x81, 0xed, 0x59, 0x5f, 0x57, 0x88,
		0x0d, 0x1a, 0x21, 0x56, 0x9e, 0x13, 0xee, 0xfd,
		0xd9, 0x51, 0x28, 0x4b, 0x5a, 0x62, 0x66, 0x49,
	})

	// chainMap is a simple index that maps a chain's genesis hash to the
	// chainCode enum for that chain.
	chainMap = map[chainhash.Hash]chainCode{
		bitcoinGenesis:  bitcoinChain,
		litecoinGenesis: litecoinChain,
	}

	// reverseChainMap is the inverse of the chainMap above: it maps the
	// chain enum for a chain to its genesis hash.
	reverseChainMap = map[chainCode]chainhash.Hash{
		bitcoinChain:  bitcoinGenesis,
		litecoinChain: litecoinGenesis,
	}
)

// chainRegistry keeps track of the current chains
type chainRegistry struct {
	sync.RWMutex

	activeChains map[chainCode]*chainControl
	netParams    map[chainCode]*bitcoinNetParams

	primaryChain chainCode
}

// newChainRegistry creates a new chainRegistry.
func newChainRegistry() *chainRegistry {
	return &chainRegistry{
		activeChains: make(map[chainCode]*chainControl),
		netParams:    make(map[chainCode]*bitcoinNetParams),
	}
}

// RegisterChain assigns an active chainControl instance to a target chain
// identified by its chainCode.
func (c *chainRegistry) RegisterChain(newChain chainCode, cc *chainControl) {
	c.Lock()
	c.activeChains[newChain] = cc
	c.Unlock()
}

// LookupChain attempts to lookup an active chainControl instance for the
// target chain.
func (c *chainRegistry) LookupChain(targetChain chainCode) (*chainControl, bool) {
	c.RLock()
	cc, ok := c.activeChains[targetChain]
	c.RUnlock()
	return cc, ok
}

// LookupChainByHash attempts to look up an active chainControl which
// corresponds to the passed genesis hash.
func (c *chainRegistry) LookupChainByHash(chainHash chainhash.Hash) (*chainControl, bool) {
	c.RLock()
	defer c.RUnlock()

	targetChain, ok := chainMap[chainHash]
	if !ok {
		return nil, ok
	}

	cc, ok := c.activeChains[targetChain]
	return cc, ok
}

// RegisterPrimaryChain sets a target chain as the "home chain" for lnd.
func (c *chainRegistry) RegisterPrimaryChain(cc chainCode) {
	c.Lock()
	defer c.Unlock()

	c.primaryChain = cc
}

// PrimaryChain returns the primary chain for this running lnd instance. The
// primary chain is considered the "home base" while the other registered
// chains are treated as secondary chains.
func (c *chainRegistry) PrimaryChain() chainCode {
	c.RLock()
	defer c.RUnlock()

	return c.primaryChain
}

// ActiveChains returns the total number of active chains.
func (c *chainRegistry) ActiveChains() []chainCode {
	c.RLock()
	defer c.RUnlock()

	chains := make([]chainCode, 0, len(c.activeChains))
	for activeChain := range c.activeChains {
		chains = append(chains, activeChain)
	}

	return chains
}

// NumActiveChains returns the total number of active chains.
func (c *chainRegistry) NumActiveChains() uint32 {
	c.RLock()
	defer c.RUnlock()

	return uint32(len(c.activeChains))
}
<|endoftext|>


<commit_before>package rollrus

import (
	"fmt"
	"os"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/stvp/roll"
)

var defaultTriggerLevels = []log.Level{
	log.ErrorLevel,
	log.FatalLevel,
	log.PanicLevel,
}

// wellKnownErrorFields are fields that are expected to be of type `error`
// in priority order.
var wellKnownErrorFields = []string{
	"err", "error",
}

// Hook wrapper for the rollbar Client
// May be used as a rollbar client itself
type Hook struct {
	roll.Client
	triggers []log.Level
}

// Setup a new hook with default reporting levels, useful for adding to
// your own logger instance.
func NewHook(token string, env string) *Hook {
	return NewHookForLevels(token, env, defaultTriggerLevels)
}

// Setup a new hook with specified reporting levels, useful for adding to
// your own logger instance.
func NewHookForLevels(token string, env string, levels []log.Level) *Hook {
	return &Hook{
		Client:   roll.New(token, env),
		triggers: levels,
	}
}

// SetupLogging sets up logging. If token is not an empty string a rollbar
// hook is added with the environment set to env. The log formatter is set to a
// TextFormatter with timestamps disabled, which is suitable for use on Heroku.
func SetupLogging(token, env string) {
	setupLogging(token, env, defaultTriggerLevels)
}

// SetupLoggingForLevels works like SetupLogging, but allows you to
// set the levels on which to trigger this hook.
func SetupLoggingForLevels(token, env string, levels []log.Level) {
	setupLogging(token, env, levels)
}

func setupLogging(token, env string, levels []log.Level) {
	log.SetFormatter(&log.TextFormatter{DisableTimestamp: true})

	if token != "" {
		log.AddHook(NewHookForLevels(token, env, levels))
	}
}

// ReportPanic attempts to report the panic to rollbar using the provided
// client and then re-panic. If it can't report the panic it will print an
// error to stderr.
func (r *Hook) ReportPanic() {
	if p := recover(); p != nil {
		if _, err := r.Client.Critical(fmt.Errorf("panic: %q", p), nil); err != nil {
			fmt.Fprintf(os.Stderr, "reporting_panic=false err=%q\n", err)
		}
		panic(p)
	}
}

// ReportPanic attempts to report the panic to rollbar if the token is set
func ReportPanic(token, env string) {
	if token != "" {
		h := &Hook{Client: roll.New(token, env)}
		h.ReportPanic()
	}
}

// Fire the hook. This is called by Logrus for entries that match the levels
// returned by Levels(). See below.
func (r *Hook) Fire(entry *log.Entry) error {
	cause, trace := extractError(entry)
	m := convertFields(entry.Data)
	if _, exists := m["time"]; !exists {
		m["time"] = entry.Time.Format(time.RFC3339)
	}

	return r.report(entry, cause, m, trace)
}

func (r *Hook) report(entry *log.Entry, cause error, m map[string]string, trace []uintptr) (err error) {
	hasTrace := len(trace) > 0
	level := entry.Level

	switch {
	case hasTrace && level == log.FatalLevel:
		_, err = r.Client.CriticalStack(cause, trace, m)
	case hasTrace && level == log.PanicLevel:
		_, err = r.Client.CriticalStack(cause, trace, m)
	case hasTrace && level == log.ErrorLevel:
		_, err = r.Client.ErrorStack(cause, trace, m)
	case hasTrace && level == log.WarnLevel:
		_, err = r.Client.WarningStack(cause, trace, m)
	case level == log.FatalLevel || level == log.PanicLevel:
		_, err = r.Client.Critical(cause, m)
	case level == log.ErrorLevel:
		_, err = r.Client.Error(cause, m)
	case level == log.WarnLevel:
		_, err = r.Client.Warning(cause, m)
	case level == log.InfoLevel:
		_, err = r.Client.Info(entry.Message, m)
	case level == log.DebugLevel:
		_, err = r.Client.Debug(entry.Message, m)
	}
	return err
}

// Levels returns the logrus log levels that this hook handles
func (r *Hook) Levels() []log.Level {
	if r.triggers == nil {
		return defaultTriggerLevels
	}
	return r.triggers
}

// convertFields converts from log.Fields to map[string]string so that we can
// report extra fields to Rollbar
func convertFields(fields log.Fields) map[string]string {
	m := make(map[string]string)
	for k, v := range fields {
		switch t := v.(type) {
		case time.Time:
			m[k] = t.Format(time.RFC3339)
		default:
			if s, ok := v.(fmt.Stringer); ok {
				m[k] = s.String()
			} else {
				m[k] = fmt.Sprintf("%+v", t)
			}
		}
	}

	return m
}

// extractError attempts to extract an error from a well known field, err or error
func extractError(entry *log.Entry) (error, []uintptr) {
	var trace []uintptr
	fields := entry.Data

	type stackTracer interface {
		StackTrace() errors.StackTrace
	}

	for _, f := range wellKnownErrorFields {
		e, ok := fields[f]
		if !ok {
			continue
		}
		err, ok := e.(error)
		if !ok {
			continue
		}

		cause := errors.Cause(err)
		tracer, ok := err.(stackTracer)
		if ok {
			return cause, copyStackTrace(tracer.StackTrace())
		}
		return cause, trace
	}

	// when no error found, default to the logged message.
	return fmt.Errorf(entry.Message), trace
}

func copyStackTrace(trace errors.StackTrace) (out []uintptr) {
	for _, frame := range trace {
		out = append(out, uintptr(frame))
	}
	return
}
<commit_msg>Update docs to pass lint<commit_after>package rollrus

import (
	"fmt"
	"os"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/stvp/roll"
)

var defaultTriggerLevels = []log.Level{
	log.ErrorLevel,
	log.FatalLevel,
	log.PanicLevel,
}

// wellKnownErrorFields are fields that are expected to be of type `error`
// in priority order.
var wellKnownErrorFields = []string{
	"err", "error",
}

// Hook wrapper for the rollbar Client
// May be used as a rollbar client itself
type Hook struct {
	roll.Client
	triggers []log.Level
}

// NewHook for use with when adding to you own logger instance. Uses the defualt
// report levels.
func NewHook(token string, env string) *Hook {
	return NewHookForLevels(token, env, defaultTriggerLevels)
}

// NewHookForLevels provided by the caller. Otherwise works like NewHook.
func NewHookForLevels(token string, env string, levels []log.Level) *Hook {
	return &Hook{
		Client:   roll.New(token, env),
		triggers: levels,
	}
}

// SetupLogging sets up logging. If token is not an empty string a rollbar
// hook is added with the environment set to env. The log formatter is set to a
// TextFormatter with timestamps disabled, which is suitable for use on Heroku.
func SetupLogging(token, env string) {
	setupLogging(token, env, defaultTriggerLevels)
}

// SetupLoggingForLevels works like SetupLogging, but allows you to
// set the levels on which to trigger this hook.
func SetupLoggingForLevels(token, env string, levels []log.Level) {
	setupLogging(token, env, levels)
}

func setupLogging(token, env string, levels []log.Level) {
	log.SetFormatter(&log.TextFormatter{DisableTimestamp: true})

	if token != "" {
		log.AddHook(NewHookForLevels(token, env, levels))
	}
}

// ReportPanic attempts to report the panic to rollbar using the provided
// client and then re-panic. If it can't report the panic it will print an
// error to stderr.
func (r *Hook) ReportPanic() {
	if p := recover(); p != nil {
		if _, err := r.Client.Critical(fmt.Errorf("panic: %q", p), nil); err != nil {
			fmt.Fprintf(os.Stderr, "reporting_panic=false err=%q\n", err)
		}
		panic(p)
	}
}

// ReportPanic attempts to report the panic to rollbar if the token is set
func ReportPanic(token, env string) {
	if token != "" {
		h := &Hook{Client: roll.New(token, env)}
		h.ReportPanic()
	}
}

// Fire the hook. This is called by Logrus for entries that match the levels
// returned by Levels(). See below.
func (r *Hook) Fire(entry *log.Entry) error {
	cause, trace := extractError(entry)
	m := convertFields(entry.Data)
	if _, exists := m["time"]; !exists {
		m["time"] = entry.Time.Format(time.RFC3339)
	}

	return r.report(entry, cause, m, trace)
}

func (r *Hook) report(entry *log.Entry, cause error, m map[string]string, trace []uintptr) (err error) {
	hasTrace := len(trace) > 0
	level := entry.Level

	switch {
	case hasTrace && level == log.FatalLevel:
		_, err = r.Client.CriticalStack(cause, trace, m)
	case hasTrace && level == log.PanicLevel:
		_, err = r.Client.CriticalStack(cause, trace, m)
	case hasTrace && level == log.ErrorLevel:
		_, err = r.Client.ErrorStack(cause, trace, m)
	case hasTrace && level == log.WarnLevel:
		_, err = r.Client.WarningStack(cause, trace, m)
	case level == log.FatalLevel || level == log.PanicLevel:
		_, err = r.Client.Critical(cause, m)
	case level == log.ErrorLevel:
		_, err = r.Client.Error(cause, m)
	case level == log.WarnLevel:
		_, err = r.Client.Warning(cause, m)
	case level == log.InfoLevel:
		_, err = r.Client.Info(entry.Message, m)
	case level == log.DebugLevel:
		_, err = r.Client.Debug(entry.Message, m)
	}
	return err
}

// Levels returns the logrus log levels that this hook handles
func (r *Hook) Levels() []log.Level {
	if r.triggers == nil {
		return defaultTriggerLevels
	}
	return r.triggers
}

// convertFields converts from log.Fields to map[string]string so that we can
// report extra fields to Rollbar
func convertFields(fields log.Fields) map[string]string {
	m := make(map[string]string)
	for k, v := range fields {
		switch t := v.(type) {
		case time.Time:
			m[k] = t.Format(time.RFC3339)
		default:
			if s, ok := v.(fmt.Stringer); ok {
				m[k] = s.String()
			} else {
				m[k] = fmt.Sprintf("%+v", t)
			}
		}
	}

	return m
}

// extractError attempts to extract an error from a well known field, err or error
func extractError(entry *log.Entry) (error, []uintptr) {
	var trace []uintptr
	fields := entry.Data

	type stackTracer interface {
		StackTrace() errors.StackTrace
	}

	for _, f := range wellKnownErrorFields {
		e, ok := fields[f]
		if !ok {
			continue
		}
		err, ok := e.(error)
		if !ok {
			continue
		}

		cause := errors.Cause(err)
		tracer, ok := err.(stackTracer)
		if ok {
			return cause, copyStackTrace(tracer.StackTrace())
		}
		return cause, trace
	}

	// when no error found, default to the logged message.
	return fmt.Errorf(entry.Message), trace
}

func copyStackTrace(trace errors.StackTrace) (out []uintptr) {
	for _, frame := range trace {
		out = append(out, uintptr(frame))
	}
	return
}
<|endoftext|>


<commit_before>package logpeck

import ()

type Filter struct {
}

type PeckTask struct {
	Name       string
	FilterExpr string
	ESConfig   ElasticSearchConfig
	Running    bool
}

func NewPeckTask(c *PeckTaskConfig) (*PeckTask, error) {
	task := &PeckTask{
		Name:     c.Name,
		ESConfig: c.ESConfig,
		Running:  false,
	}
	return task, nil
}

func (p *PeckTask) Run() {

}

func (p *PeckTask) Pause() error {
	return nil
}

func (p *PeckTask) Cancel() error {
	return nil
}
<commit_msg>PeckTask support Start/Pause<commit_after>package logpeck

import ()

type Filter struct {
}

type PeckTask struct {
	Name       string
	FilterExpr string
	ESConfig   ElasticSearchConfig

	pause bool
}

func NewPeckTask(c *PeckTaskConfig) *PeckTask {
	task := &PeckTask{
		Name:     c.Name,
		ESConfig: c.ESConfig,
		pause:    true,
	}
	return task
}

func (p *PeckTask) Start() {
	p.pause = false
}

func (p *PeckTask) Pause() {
	p.pause = true
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/drive/v2"
)

var configDir = flag.String("config", "~/.peeweebot/", "location of config directory")
var folderId = "0B1SaB_OdyoZrVEhQR01WWXoxbjA"

func getConfigDir() string {
	usr, err := user.Current()
	if err != nil {
		log.Fatalf("Unable to get current user: %v", err)
	}
	return filepath.Clean(strings.Replace(*configDir, "~/", usr.HomeDir+"/", 1))
}

func getGoogleOAuthConfig() *oauth2.Config {
	b, err := ioutil.ReadFile(filepath.Join(getConfigDir(), "google_client_secrets.json"))
	if err != nil {
		log.Fatalf("Unable to read client secret file: %v", err)
	}

	config, err := google.ConfigFromJSON(b, drive.DriveReadonlyScope)
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}
	return config
}

func getGoogleDriveTokenFromFile() *oauth2.Token {
	filename := filepath.Join(getConfigDir(), "google_drive_oauth_token.json")
	f, err := os.Open(filename)
	if err != nil {
		log.Fatalf("Unable to open token file \"%v\": %v", filename, err)
	}
	defer f.Close()

	t := &oauth2.Token{}
	err = json.NewDecoder(f).Decode(t)
	if err != nil {
		log.Fatalf("Unable to decode token file \"%v\": %v", filename, err)
	}

	return t
}

func getGoogleDriveService(ctx context.Context) (*drive.Service, error) {
	return drive.New(
		getGoogleOAuthConfig().Client(
			ctx,
			getGoogleDriveTokenFromFile(),
		),
	)
}

func getAllChildren(driveService *drive.Service, folder string) (list []*drive.ChildReference) {
	var pageToken string
	for {
		call := driveService.Children.List(folder)
		if pageToken != "" {
			call.PageToken(pageToken)
		}

		r, err := call.Do()
		if err != nil {
			log.Fatalf("Unable to retrieve files.", err)
		}

		list = append(list, r.Items...)

		pageToken = r.NextPageToken

		if pageToken == "" {
			break
		}
	}
	return
}

func main() {
	rand.Seed(time.Now().Unix())
	ctx := context.Background()
	driveService, err := getGoogleDriveService(ctx)
	if err != nil {
		log.Fatalf("Unable to get google drive service: %v", err)
	}

	fileList := getAllChildren(driveService, folderId)

	fileNumber := rand.Intn(len(fileList))
	fmt.Printf("selected %vth file\n", fileNumber)
	selectedFile := fileList[fileNumber]

	fileMetadata, err := driveService.Files.Get(selectedFile.Id).Do()
	if err != nil {
		log.Fatalf("Unable to get filemetadata: %v", err)
	}

	extension := fileMetadata.FileExtension

	fileResponse, err := driveService.Files.Get(selectedFile.Id).Download()
	if err != nil {
		log.Fatalf("Unable to fetch file: %v", err)
	}
	defer fileResponse.Body.Close()

	fd, err := os.Create("picture." + extension)
	if err != nil {
		log.Fatalf("Unable to open file for writing: %v", err)
	}

	n, err := io.Copy(fd, fileResponse.Body)
	if err != nil {
		log.Fatalf("Unable to write file to disk fully (%v bytes written): %v", n, err)
	}
}
<commit_msg>add twitter stuff<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"time"

	"github.com/ChimeraCoder/anaconda"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/drive/v2"
)

var configDir = flag.String("config", "~/.peeweebot/", "location of config directory")
var folderId = "0B1SaB_OdyoZrVEhQR01WWXoxbjA"

func getConfigDir() string {
	usr, err := user.Current()
	if err != nil {
		log.Fatalf("Unable to get current user: %v", err)
	}
	return filepath.Clean(strings.Replace(*configDir, "~/", usr.HomeDir+"/", 1))
}

func getGoogleOAuthConfig() *oauth2.Config {
	b, err := ioutil.ReadFile(filepath.Join(getConfigDir(), "google_client_secrets.json"))
	if err != nil {
		log.Fatalf("Unable to read client secret file: %v", err)
	}

	config, err := google.ConfigFromJSON(b, drive.DriveReadonlyScope)
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}
	return config
}

func getGoogleDriveTokenFromFile() *oauth2.Token {
	filename := filepath.Join(getConfigDir(), "google_drive_oauth_token.json")
	f, err := os.Open(filename)
	if err != nil {
		log.Fatalf("Unable to open token file \"%v\": %v", filename, err)
	}
	defer f.Close()

	t := &oauth2.Token{}
	err = json.NewDecoder(f).Decode(t)
	if err != nil {
		log.Fatalf("Unable to decode token file \"%v\": %v", filename, err)
	}

	return t
}

func getGoogleDriveService(ctx context.Context) (*drive.Service, error) {
	return drive.New(
		getGoogleOAuthConfig().Client(
			ctx,
			getGoogleDriveTokenFromFile(),
		),
	)
}

func getAllChildren(driveService *drive.Service, folder string) (list []*drive.ChildReference) {
	var pageToken string
	for {
		call := driveService.Children.List(folder)
		if pageToken != "" {
			call.PageToken(pageToken)
		}

		r, err := call.Do()
		if err != nil {
			log.Fatalf("Unable to retrieve files.", err)
		}

		list = append(list, r.Items...)

		pageToken = r.NextPageToken

		if pageToken == "" {
			break
		}
	}
	return
}

type TwitterStuff struct {
	ConsumerKey       string
	ConsumerSecret    string
	AccessToken       string
	AccessTokenSecret string
}

func getTwitterClient() *anaconda.TwitterApi {
	fd, err := os.Open(filepath.Join(getConfigDir(), "twitter_stuff.json"))
	if err != nil {
		log.Fatalf("Unable to open twitter_stuff.json: %v", err)
	}
	defer fd.Close()

	twitterStuff := TwitterStuff{}
	err = json.NewDecoder(fd).Decode(&twitterStuff)
	if err != nil {
		log.Fatalf("Unable to decode twitter_stuff.json: %v", err)
	}

	anaconda.SetConsumerKey(twitterStuff.ConsumerKey)
	anaconda.SetConsumerSecret(twitterStuff.ConsumerSecret)
	return anaconda.NewTwitterApi(
		twitterStuff.AccessToken,
		twitterStuff.AccessTokenSecret,
	)
}

func main() {
	rand.Seed(time.Now().Unix())
	ctx := context.Background()
	driveService, err := getGoogleDriveService(ctx)
	if err != nil {
		log.Fatalf("Unable to get google drive service: %v", err)
	}

	fileList := getAllChildren(driveService, folderId)

	fileNumber := rand.Intn(len(fileList))
	fmt.Printf("selected %vth file\n", fileNumber)
	selectedFile := fileList[fileNumber]

	fileMetadata, err := driveService.Files.Get(selectedFile.Id).Do()
	if err != nil {
		log.Fatalf("Unable to get filemetadata: %v", err)
	}

	extension := fileMetadata.FileExtension

	fileResponse, err := driveService.Files.Get(selectedFile.Id).Download()
	if err != nil {
		log.Fatalf("Unable to fetch file: %v", err)
	}
	defer fileResponse.Body.Close()

	fd, err := os.Create("picture." + extension)
	if err != nil {
		log.Fatalf("Unable to open file for writing: %v", err)
	}
	defer fd.Close()

	n, err := io.Copy(fd, fileResponse.Body)
	if err != nil {
		log.Fatalf("Unable to write file to disk fully (%v bytes written): %v", n, err)
	}

	twitterApi := getTwitterClient()

	tweet, err := twitterApi.PostTweet("test tweet", nil)
	if err != nil {
		log.Fatalf("Unable to post tweet: %v", err)
	}

	fmt.Println(tweet)
}
<|endoftext|>


<commit_before>package main

func (this SingleProducerSequencer) Next(slotCount int64) int64 {
	nextValue := this.pad.Load()
	nextSequence := nextValue + slotCount
	wrapPoint := nextSequence - this.ringSize
	cachedGatingSequence := this.pad[cachedGatingSequencePadIndex]

	if wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue {
		minSequence := int64(0)
		for wrapPoint > minSequence {
			minSequence = this.last.Load()
		}

		this.pad[cachedGatingSequencePadIndex] = minSequence
	}

	this.pad.Store(nextSequence)
	return nextSequence
}

func (this SingleProducerSequencer) Publish(sequence int64) {
	this.cursor.Store(sequence)
}

func NewSingleProducerSequencer(cursor *Sequence, ringSize int32, last Barrier) SingleProducerSequencer {
	pad := NewSequence()
	pad[cachedGatingSequencePadIndex] = InitialSequenceValue

	return SingleProducerSequencer{
		pad:      pad,
		cursor:   cursor,
		ringSize: int64(ringSize),
		last:     last,
	}
}

type SingleProducerSequencer struct {
	pad      *Sequence
	cursor   *Sequence
	ringSize int64
	last     Barrier
}

const cachedGatingSequencePadIndex = 1
<commit_msg>Using a pointer instead of a struct makes it 16x faster.<commit_after>package main

func (this *SingleProducerSequencer) Next(slotCount int64) int64 {
	nextValue := this.pad.Load()
	nextSequence := nextValue + slotCount
	wrapPoint := nextSequence - this.ringSize
	cachedGatingSequence := this.pad[cachedGatingSequencePadIndex]

	if wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue {
		minSequence := int64(0)
		for wrapPoint > minSequence {
			minSequence = this.last.Load()
		}

		this.pad[cachedGatingSequencePadIndex] = minSequence
	}

	this.pad.Store(nextSequence)
	return nextSequence
}

func (this *SingleProducerSequencer) Publish(sequence int64) {
	this.cursor[0] = sequence
}

func NewSingleProducerSequencer(cursor *Sequence, ringSize int32, last Barrier) *SingleProducerSequencer {
	pad := NewSequence()
	pad[cachedGatingSequencePadIndex] = InitialSequenceValue

	return &SingleProducerSequencer{
		pad:      pad,
		cursor:   cursor,
		ringSize: int64(ringSize),
		last:     last,
	}
}

type SingleProducerSequencer struct {
	pad      *Sequence
	cursor   *Sequence
	ringSize int64
	last     Barrier
}

const cachedGatingSequencePadIndex = 1
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"os"
	"text/tabwriter"

	"github.com/GaryBoone/GoStats/stats"
	"github.com/topher200/baseutil"
)

type criterionCalculationFunction func(teams []Team) Score
type criterion struct {
	name      string                       // human readable name
	calculate criterionCalculationFunction // how to calculate the raw score
	filter    PlayerFilter                 // cull down to players that match
	weight    int                          // how much weight to give this score
	// worstCase is calculated at runtime to be the absolute worst score we can
	// see this criterion getting, calculated using random sampling
	worstCase Score
}

var criteriaToScore = [...]criterion{
	criterion{"matching baggages", baggagesMatch, nil, 10000, 0},
	criterion{"number of players", playerCountDifference, nil, 15, 0},
	criterion{"number of males", playerCountDifference, IsMale, 12, 0},
	criterion{"number of females", playerCountDifference, IsFemale, 12, 0},
	criterion{"average rating players", ratingDifference, nil, 8, 0},
	criterion{"average rating males", ratingDifference, IsMale, 7, 0},
	criterion{"average rating females", ratingDifference, IsFemale, 7, 0},
	criterion{"std dev of team player ratings", ratingStdDev, nil, 6, 0},
	criterion{"std dev of team male ratings", ratingStdDev, IsMale, 5, 0},
	criterion{"std dev of team female ratings", ratingStdDev, IsFemale, 5, 0},
}

func playerCountDifference(teams []Team) Score {
	teamLengths := make([]int, numTeams)
	for i, team := range teams {
		teamLengths[i] = len(team.players)
	}
	return Score(baseutil.StandardDeviationInt(teamLengths))
}

func ratingDifference(teams []Team) Score {
	teamAverageRatings := make([]float64, numTeams)
	for i, team := range teams {
		teamAverageRatings[i] = float64(AverageRating(team))
	}
	return Score(stats.StatsSampleStandardDeviation(teamAverageRatings))
}

func ratingStdDev(teams []Team) Score {
	teamRatingsStdDev := make([]float64, numTeams)
	for i, team := range teams {
		if len(team.players) < 2 {
			teamRatingsStdDev[i] = 0
			continue
		}
		playerRatings := make([]float64, len(team.players))
		for j, player := range team.players {
			playerRatings[j] = float64(player.rating)
		}
		teamRatingsStdDev[i] = stats.StatsSampleStandardDeviation(playerRatings)
	}
	return Score(stats.StatsSampleStandardDeviation(teamRatingsStdDev))
}

func baggagesMatch(teams []Team) Score {
	score := Score(0)
	for _, team := range teams {
		for _, player := range team.players {
			if !player.HasBaggage() {
				continue
			}
			_, err := FindPlayer(team.players, player.baggage)
			if err != nil {
				// Player desired a baggage, but they're not on the team
				score += 1
			}
		}
	}
	return score
}

func AverageRating(team Team) Score {
	if len(team.players) == 0 {
		return Score(0)
	}
	sum := float32(0.0)
	for _, player := range team.players {
		sum += player.rating
	}
	return Score(sum / float32(len(team.players)))
}

// analyze criterion by filtering the input teams and running the criterion's
// function
func (c criterion) analyze(teams []Team) (
	rawScore Score, normalizedScore Score, weightedScore Score) {
	filteredTeams := make([]Team, len(teams))
	for i, _ := range teams {
		filteredTeams[i].players = Filter(teams[i].players, c.filter)
	}

	rawScore = c.calculate(filteredTeams)
	if c.worstCase != 0 {
		normalizedScore = rawScore / c.worstCase
	} else {
		normalizedScore = rawScore
	}
	weightedScore = normalizedScore * Score(c.weight)
	return rawScore, normalizedScore, weightedScore
}

func maxScore(a, b Score) Score {
	if a > b {
		return a
	} else {
		return b
	}
}

// PopulateWorstCases calculates the worst case of each criterion.
//
// The function has the side effect of filling in the worstCase param for each
// criterion in criteriaToScore.
func PopulateWorstCases(solutions []Solution) {
	for _, solution := range solutions {
		_, rawScores := ScoreSolution(solution.players)
		for i, criterion := range criteriaToScore {
			if math.IsNaN(float64(rawScores[i])) {
				continue
			}
			criteriaToScore[i].worstCase = maxScore(
				criterion.worstCase, rawScores[i])
		}
	}
}

// Score a solution based on all known criteria.
//
// Returns the total score for the solution, as well as the raw score found for
// each of the criteriaToScore.
func ScoreSolution(players []Player) (totalScore Score, rawScores []Score) {
	teams := splitIntoTeams(players)
	rawScores = make([]Score, len(criteriaToScore))
	for i, criterion := range criteriaToScore {
		rawScore, _, weightedScore := criterion.analyze(teams)
		rawScores[i] = rawScore
		totalScore += weightedScore
	}
	return totalScore, rawScores
}

func PrintSolutionScoring(solution Solution) {
	teams := splitIntoTeams(solution.players)
	totalScore := Score(0)
	writer := new(tabwriter.Writer)
	writer.Init(os.Stdout, 0, 0, 1, ' ', 0)
	for _, criterion := range criteriaToScore {
		rawScore, normalizedScore, weightedScore := criterion.analyze(teams)
		totalScore += weightedScore
		fmt.Fprintf(
			writer,
			"Balancing %s.\tScore: %.02f\t(= normalized score %.02f * weight %d)\t(raw score %0.2f, worst case %.02f)\tRunning total: %.02f\n",
			criterion.name, weightedScore, normalizedScore, criterion.weight,
			rawScore, criterion.worstCase, totalScore)
	}
	writer.Flush()
}
<commit_msg>Revert "Revert "balance the rating of the top players""<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"sort"
	"text/tabwriter"

	"github.com/GaryBoone/GoStats/stats"
	"github.com/topher200/baseutil"
)

type criterionCalculationFunction func(teams []Team) Score
type criterion struct {
	name      string                       // human readable name
	calculate criterionCalculationFunction // how to calculate the raw score
	filter    PlayerFilter                 // cull down to players that match
	// numPlayers reduces the amount of players we analyze from each team.
	// Sometimes used to just grab the top players on the team, for example.
	// Ignored if 0.
	numPlayers int
	weight     int // how much weight to give this score
	// worstCase is calculated at runtime to be the absolute worst score we can
	// see this criterion getting, calculated using random sampling
	worstCase Score
}

var criteriaToScore = [...]criterion{
	criterion{"matching baggages", baggagesMatch, nil, 0, 10000, 0},
	criterion{"number of players", playerCountDifference, nil, 0, 15, 0},
	criterion{"number of males", playerCountDifference, IsMale, 0, 12, 0},
	criterion{"number of females", playerCountDifference, IsFemale, 0, 12, 0},
	criterion{"average rating players", ratingDifference, nil, 0, 8, 0},
	criterion{"average rating males", ratingDifference, IsMale, 0, 7, 0},
	criterion{"average rating females", ratingDifference, IsFemale, 0, 7, 0},
	criterion{"average rating top players", ratingDifference, nil, 3, 20, 0},
	criterion{"average rating top males", ratingDifference, IsMale, 3, 19, 0},
	criterion{"average rating top females", ratingDifference, IsFemale, 19, 7, 0},
	criterion{"std dev of team player ratings", ratingStdDev, nil, 0, 6, 0},
	criterion{"std dev of team male ratings", ratingStdDev, IsMale, 0, 5, 0},
	criterion{"std dev of team female ratings", ratingStdDev, IsFemale, 0, 5, 0},
}

func playerCountDifference(teams []Team) Score {
	teamLengths := make([]int, numTeams)
	for i, team := range teams {
		teamLengths[i] = len(team.players)
	}
	return Score(baseutil.StandardDeviationInt(teamLengths))
}

func ratingDifference(teams []Team) Score {
	teamAverageRatings := make([]float64, numTeams)
	for i, team := range teams {
		teamAverageRatings[i] = float64(AverageRating(team))
	}
	return Score(stats.StatsSampleStandardDeviation(teamAverageRatings))
}

func ratingStdDev(teams []Team) Score {
	teamRatingsStdDev := make([]float64, numTeams)
	for i, team := range teams {
		if len(team.players) < 2 {
			teamRatingsStdDev[i] = 0
			continue
		}
		playerRatings := make([]float64, len(team.players))
		for j, player := range team.players {
			playerRatings[j] = float64(player.rating)
		}
		teamRatingsStdDev[i] = stats.StatsSampleStandardDeviation(playerRatings)
	}
	return Score(stats.StatsSampleStandardDeviation(teamRatingsStdDev))
}

func baggagesMatch(teams []Team) Score {
	score := Score(0)
	for _, team := range teams {
		for _, player := range team.players {
			if !player.HasBaggage() {
				continue
			}
			_, err := FindPlayer(team.players, player.baggage)
			if err != nil {
				// Player desired a baggage, but they're not on the team
				score += 1
			}
		}
	}
	return score
}

func AverageRating(team Team) Score {
	if len(team.players) == 0 {
		return Score(0)
	}
	sum := float32(0.0)
	for _, player := range team.players {
		sum += player.rating
	}
	return Score(sum / float32(len(team.players)))
}

// analyze criterion by filtering the input teams and running the criterion's
// function
func (c criterion) analyze(teams []Team) (
	rawScore Score, normalizedScore Score, weightedScore Score) {
	filteredTeams := make([]Team, len(teams))
	for i, _ := range teams {
		players := Filter(teams[i].players, c.filter)
		// If the max num players to run this criterion on is set and we have at
		// least that many players, filter out all but the top ones
		if c.numPlayers > 0 && len(players) > c.numPlayers {
			sort.Sort(ByRating(players))
			players = players[:c.numPlayers]
		}
		filteredTeams[i].players = players
	}

	rawScore = c.calculate(filteredTeams)
	if c.worstCase != 0 {
		normalizedScore = rawScore / c.worstCase
	} else {
		normalizedScore = rawScore
	}
	weightedScore = normalizedScore * Score(c.weight)
	return rawScore, normalizedScore, weightedScore
}

func maxScore(a, b Score) Score {
	if a > b {
		return a
	} else {
		return b
	}
}

// PopulateWorstCases calculates the worst case of each criterion.
//
// The function has the side effect of filling in the worstCase param for each
// criterion in criteriaToScore.
func PopulateWorstCases(solutions []Solution) {
	for _, solution := range solutions {
		_, rawScores := ScoreSolution(solution.players)
		for i, criterion := range criteriaToScore {
			if math.IsNaN(float64(rawScores[i])) {
				continue
			}
			criteriaToScore[i].worstCase = maxScore(
				criterion.worstCase, rawScores[i])
		}
	}
}

// Score a solution based on all known criteria.
//
// Returns the total score for the solution, as well as the raw score found for
// each of the criteriaToScore.
func ScoreSolution(players []Player) (totalScore Score, rawScores []Score) {
	teams := splitIntoTeams(players)
	rawScores = make([]Score, len(criteriaToScore))
	for i, criterion := range criteriaToScore {
		rawScore, _, weightedScore := criterion.analyze(teams)
		rawScores[i] = rawScore
		totalScore += weightedScore
	}
	return totalScore, rawScores
}

func PrintSolutionScoring(solution Solution) {
	teams := splitIntoTeams(solution.players)
	totalScore := Score(0)
	writer := new(tabwriter.Writer)
	writer.Init(os.Stdout, 0, 0, 1, ' ', 0)
	for _, criterion := range criteriaToScore {
		rawScore, normalizedScore, weightedScore := criterion.analyze(teams)
		totalScore += weightedScore
		fmt.Fprintf(
			writer,
			"Balancing %s.\tScore: %.02f\t(= normalized score %.02f * weight %d)\t(raw score %0.2f, worst case %.02f)\tRunning total: %.02f\n",
			criterion.name, weightedScore, normalizedScore, criterion.weight,
			rawScore, criterion.worstCase, totalScore)
	}
	writer.Flush()
}
<|endoftext|>


<commit_before>package main

var scrtsMap = make(map[string]map[string]interface{})
var scrtsSlice = make(map[string][]interface{})

//////////////////////////////////////////////////////////////////////////////
func scratchMapSet(scratch string, key string, value interface{}) {
	if scr, ok := scrtsMap[scratch]; ok {
		scr[key] = value
	} else {
		scrtsMap[scratch] = make(map[string]interface{})
		scrtsMap[scratch][key] = value
	}
}

//////////////////////////////////////////////////////////////////////////////
func scratchSliceAdd(scratch string, value interface{}) {
	if scr, ok := scrtsSlice[scratch]; ok {
		scr = append(scr, value)
	} else {
		scrtsSlice[scratch] = make([]interface{}, 0)
		scrtsSlice[scratch] = append(scrtsSlice[scratch], value)
	}
}

//////////////////////////////////////////////////////////////////////////////
func scratchGetMapValue(scratch string, key string) interface{} {
	if scr, ok := scrtsMap[scratch]; ok {
		return scr[key]
	}
	return nil
}

//////////////////////////////////////////////////////////////////////////////
func scratchGetSliceValues(scratch string, key string) []interface{} {
	if scr, ok := scrtsSlice[scratch]; ok {
		return scr
	}
	return nil
}

//////////////////////////////////////////////////////////////////////////////
func scratchMapNames() []string {
	nms := make([]string, 0)

	for k, _ := range scrtsMap {
		nms = append(nms, k)
	}
	return nms
}

//////////////////////////////////////////////////////////////////////////////
func scratchSliceNames() []string {
	nms := make([]string, 0)

	for k, _ := range scrtsSlice {
		nms = append(nms, k)
	}
	return nms
}
<commit_msg>autopush@1447076231<commit_after>package main

var scrtsMap = make(map[string]map[string]interface{})
var scrtsSlice = make(map[string][]interface{})

//////////////////////////////////////////////////////////////////////////////
func scratchMapSet(scratch string, key string, value interface{}) {
	if scr, ok := scrtsMap[scratch]; ok {
		scr[key] = value
	} else {
		scrtsMap[scratch] = make(map[string]interface{})
		scrtsMap[scratch][key] = value
	}
}

//////////////////////////////////////////////////////////////////////////////
func scratchSliceAdd(scratch string, value interface{}) error {
	if scr, ok := scrtsSlice[scratch]; ok {
		scr = append(scr, value)
	} else {
		scrtsSlice[scratch] = make([]interface{}, 0)
		scrtsSlice[scratch] = append(scrtsSlice[scratch], value)
	}

	return nil
}

//////////////////////////////////////////////////////////////////////////////
func scratchGetMapValue(scratch string, key string) interface{} {
	if scr, ok := scrtsMap[scratch]; ok {
		return scr[key]
	}
	return nil
}

//////////////////////////////////////////////////////////////////////////////
func scratchGetSliceValues(scratch string, key string) []interface{} {
	if scr, ok := scrtsSlice[scratch]; ok {
		return scr
	}
	return nil
}

//////////////////////////////////////////////////////////////////////////////
func scratchMapNames() []string {
	nms := make([]string, 0)

	for k := range scrtsMap {
		nms = append(nms, k)
	}
	return nms
}

//////////////////////////////////////////////////////////////////////////////
func scratchSliceNames() []string {
	nms := make([]string, 0)

	for k := range scrtsSlice {
		nms = append(nms, k)
	}
	return nms
}
<|endoftext|>


<commit_before>package meta

import (
	"encoding/binary"
	"fmt"
	"io"
)

// A SeekTable metadata block is an optional block for storing seek points. It
// is possible to seek to any given sample in a FLAC stream without a seek
// table, but the delay can be unpredictable since the bitrate may vary widely
// within a stream. By adding seek points to a stream, this delay can be
// significantly reduced. Each seek point takes 18 bytes, so 1% resolution
// within a stream adds less than 2k.
//
// There can be only one SEEKTABLE in a stream, but the table can have any
// number of seek points. There is also a special 'placeholder' seekpoint which
// will be ignored by decoders but which can be used to reserve space for future
// seek point insertion.
type SeekTable struct {
	// One or more seek points.
	Points []SeekPoint
}

// A SeekPoint specifies the offset of a sample.
type SeekPoint struct {
	// Sample number of first sample in the target frame, or 0xFFFFFFFFFFFFFFFF
	// for a placeholder point.
	SampleNum uint64
	// Offset (in bytes) from the first byte of the first frame header to the
	// first byte of the target frame's header.
	Offset uint64
	// Number of samples in the target frame.
	SampleCount uint16
}

// PlaceholderPoint is the sample number used for placeholder points. For
// placeholder points, the second and third field values in the SeekPoint
// structure are undefined.
const PlaceholderPoint = 0xFFFFFFFFFFFFFFFF

// NewSeekTable parses and returns a new SeekTable metadata block. The provided
// io.Reader should limit the amount of data that can be read to header.Length
// bytes.
//
// Seek table format (pseudo code):
//
//    type METADATA_BLOCK_SEEKTABLE struct {
//       // The number of seek points is implied by the metadata header 'length'
//       // field, i.e. equal to length / 18.
//       points []point
//    }
//
//    type point struct {
//       sample_num   uint64
//       offset       uint64
//       sample_count uint16
//    }
//
// ref: http://flac.sourceforge.net/format.html#metadata_block_seektable
func NewSeekTable(r io.Reader) (st *SeekTable, err error) {
	st = new(SeekTable)
	var hasPrev bool
	var prevSampleNum uint64
	for {
		var point SeekPoint
		err = binary.Read(r, binary.BigEndian, &point)
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		if hasPrev && prevSampleNum >= point.SampleNum {
			// - Seek points within a table must be sorted in ascending order by
			//   sample number.
			// - Seek points within a table must be unique by sample number, with
			//   the exception of placeholder points.
			// - The previous two notes imply that there may be any number of
			//   placeholder points, but they must all occur at the end of the
			//   table.
			if point.SampleNum != PlaceholderPoint {
				return nil, fmt.Errorf("meta.NewSeekTable: invalid seek point; sample number (%d) not in ascending order", point.SampleNum)
			}
		}
		prevSampleNum = point.SampleNum
		hasPrev = true
		st.Points = append(st.Points, point)
	}
	return st, nil
}
<commit_msg>meta: Update error handling in NewSeekTable.<commit_after>package meta

import (
	"encoding/binary"
	"fmt"
	"io"
)

// A SeekTable metadata block is an optional block for storing seek points. It
// is possible to seek to any given sample in a FLAC stream without a seek
// table, but the delay can be unpredictable since the bitrate may vary widely
// within a stream. By adding seek points to a stream, this delay can be
// significantly reduced. Each seek point takes 18 bytes, so 1% resolution
// within a stream adds less than 2k.
//
// There can be only one SEEKTABLE in a stream, but the table can have any
// number of seek points. There is also a special 'placeholder' seekpoint which
// will be ignored by decoders but which can be used to reserve space for future
// seek point insertion.
type SeekTable struct {
	// One or more seek points.
	Points []SeekPoint
}

// A SeekPoint specifies the offset of a sample.
type SeekPoint struct {
	// Sample number of first sample in the target frame, or 0xFFFFFFFFFFFFFFFF
	// for a placeholder point.
	SampleNum uint64
	// Offset (in bytes) from the first byte of the first frame header to the
	// first byte of the target frame's header.
	Offset uint64
	// Number of samples in the target frame.
	SampleCount uint16
}

// PlaceholderPoint is the sample number used for placeholder points. For
// placeholder points, the second and third field values in the SeekPoint
// structure are undefined.
const PlaceholderPoint = 0xFFFFFFFFFFFFFFFF

// NewSeekTable parses and returns a new SeekTable metadata block. The provided
// io.Reader should limit the amount of data that can be read to header.Length
// bytes.
//
// Seek table format (pseudo code):
//
//    type METADATA_BLOCK_SEEKTABLE struct {
//       // The number of seek points is implied by the metadata header 'length'
//       // field, i.e. equal to length / 18.
//       points []point
//    }
//
//    type point struct {
//       sample_num   uint64
//       offset       uint64
//       sample_count uint16
//    }
//
// ref: http://flac.sourceforge.net/format.html#metadata_block_seektable
func NewSeekTable(r io.Reader) (st *SeekTable, err error) {
	st = new(SeekTable)
	var hasPrev bool
	var prevSampleNum uint64
	for {
		var point SeekPoint
		err = binary.Read(r, binary.BigEndian, &point)
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		if hasPrev && point.SampleNum != PlaceholderPoint {
			// - Seek points within a table must be sorted in ascending order by
			//   sample number.
			// - Seek points within a table must be unique by sample number, with
			//   the exception of placeholder points.
			// - The previous two notes imply that there may be any number of
			//   placeholder points, but they must all occur at the end of the
			//   table.
			if prevSampleNum == point.SampleNum {
				return nil, fmt.Errorf("meta.NewSeekTable: invalid seek point; sample number (%d) is not unique", point.SampleNum)
			} else if prevSampleNum > point.SampleNum {
				return nil, fmt.Errorf("meta.NewSeekTable: invalid seek point; sample number (%d) is not in ascending order", point.SampleNum)
			}
		}
		prevSampleNum = point.SampleNum
		hasPrev = true
		st.Points = append(st.Points, point)
	}
	return st, nil
}
<|endoftext|>


<commit_before>package sdl

/*
#include <SDL2/SDL.h>
#include "log.h"

static inline _SDL_Log(const char *fmt)
{
    SDL_Log(fmt);
}

static inline _SDL_LogVerbose(int category, const char *fmt)
{
    SDL_LogVerbose(category, fmt);
}

static inline _SDL_LogDebug(int category, const char *fmt)
{
    SDL_LogDebug(category, fmt);
}

static inline _SDL_LogInfo(int category, const char *fmt)
{
    SDL_LogInfo(category, fmt);
}

static inline _SDL_LogWarn(int category, const char *fmt)
{
    SDL_LogWarn(category, fmt);
}

static inline _SDL_LogError(int category, const char *fmt)
{
    SDL_LogError(category, fmt);
}

static inline _SDL_LogCritical(int category, const char *fmt)
{
    SDL_LogCritical(category, fmt);
}

static inline _SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt)
{
    SDL_LogCritical(category, fmt);
}
*/
import "C"
import "fmt"
import "unsafe"

const (
	LOG_CATEGORY_APPLICATION = iota
	LOG_CATEGORY_ERROR
	LOG_CATEGORY_ASSERT
	LOG_CATEGORY_SYSTEM
	LOG_CATEGORY_AUDIO
	LOG_CATEGORY_VIDEO
	LOG_CATEGORY_RENDER
	LOG_CATEGORY_INPUT
	LOG_CATEGORY_TEST
	LOG_CATEGORY_RESERVED1
	LOG_CATEGORY_RESERVED2
	LOG_CATEGORY_RESERVED3
	LOG_CATEGORY_RESERVED4
	LOG_CATEGORY_RESERVED5
	LOG_CATEGORY_RESERVED6
	LOG_CATEGORY_RESERVED7
	LOG_CATEGORY_RESERVED8
	LOG_CATEGORY_RESERVED9
	LOG_CATEGORY_RESERVED10
	LOG_CATEGORY_CUSTOM
)

const (
	LOG_PRIORITY_VERBOSE = iota + 1
	LOG_PRIORITY_DEBUG
	LOG_PRIORITY_INFO
	LOG_PRIORITY_WARN
	LOG_PRIORITY_ERROR
	LOG_PRIORITY_CRITICAL
	NUM_LOG_PRIORITIES
)

type LogPriority C.SDL_LogPriority

func (p LogPriority) c() C.SDL_LogPriority {
	return C.SDL_LogPriority(p)
}

func LogSetAllPriority(p LogPriority) {
	C.SDL_LogSetAllPriority(p.c())
}

func LogSetPriority(category int, p LogPriority) {
	C.SDL_LogSetPriority(C.int(category), p.c())
}

func LogGetPriority(category int) LogPriority {
	return LogPriority(C.SDL_LogGetPriority(C.int(category)))
}

func LogResetPriorities() {
	C.SDL_LogResetPriorities()
}

func Log(str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_Log(cstr)
}

func LogVerbose(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogVerbose(C.int(cat), cstr)
}

func LogDebug(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogDebug(C.int(cat), cstr)
}

func LogInfo(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogInfo(C.int(cat), cstr)
}

func LogWarn(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogWarn(C.int(cat), cstr)
}

func LogError(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogError(C.int(cat), cstr)
}

func LogCritical(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogCritical(C.int(cat), cstr)
}

func LogMessage(cat int, pri LogPriority, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogMessage(C.int(cat), C.SDL_LogPriority(pri), cstr)
}

type LogOutputFunction func(data interface{}, cat int, pri LogPriority, message string)

type logOutputFunctionCtx struct {
    f LogOutputFunction
        d interface{}
}

// Yissakhar Z. Beck (DeedleFake)'s implementation
//
//export logOutputFunction
func logOutputFunction(data unsafe.Pointer, cat C.int, pri C.SDL_LogPriority, message *C.char) {
    ctx := (*logOutputFunctionCtx)(data)

    ctx.f(ctx.d, int(cat), LogPriority(pri), C.GoString(message))
}

var (
    logOutputFunctionCache LogOutputFunction
    logOutputDataCache interface{}
)

func LogGetOutputFunction() (LogOutputFunction, interface{}) {
    return logOutputFunctionCache, logOutputDataCache
}

func LogSetOutputFunction(f LogOutputFunction, data interface{}) {
    ctx := &logOutputFunctionCtx{
            f: f,
            d: data,
    }

    C.LogSetOutputFunction(unsafe.Pointer(ctx))

    logOutputFunctionCache = f
    logOutputDataCache = data
}
<commit_msg>Fixed some C functions not having return types<commit_after>package sdl

/*
#include <SDL2/SDL.h>
#include "log.h"

static inline void _SDL_Log(const char *fmt)
{
    SDL_Log(fmt);
}

static inline void _SDL_LogVerbose(int category, const char *fmt)
{
    SDL_LogVerbose(category, fmt);
}

static inline void _SDL_LogDebug(int category, const char *fmt)
{
    SDL_LogDebug(category, fmt);
}

static inline void _SDL_LogInfo(int category, const char *fmt)
{
    SDL_LogInfo(category, fmt);
}

static inline void _SDL_LogWarn(int category, const char *fmt)
{
    SDL_LogWarn(category, fmt);
}

static inline void _SDL_LogError(int category, const char *fmt)
{
    SDL_LogError(category, fmt);
}

static inline void _SDL_LogCritical(int category, const char *fmt)
{
    SDL_LogCritical(category, fmt);
}

static inline void _SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt)
{
    SDL_LogCritical(category, fmt);
}
*/
import "C"
import "fmt"
import "unsafe"

const (
	LOG_CATEGORY_APPLICATION = iota
	LOG_CATEGORY_ERROR
	LOG_CATEGORY_ASSERT
	LOG_CATEGORY_SYSTEM
	LOG_CATEGORY_AUDIO
	LOG_CATEGORY_VIDEO
	LOG_CATEGORY_RENDER
	LOG_CATEGORY_INPUT
	LOG_CATEGORY_TEST
	LOG_CATEGORY_RESERVED1
	LOG_CATEGORY_RESERVED2
	LOG_CATEGORY_RESERVED3
	LOG_CATEGORY_RESERVED4
	LOG_CATEGORY_RESERVED5
	LOG_CATEGORY_RESERVED6
	LOG_CATEGORY_RESERVED7
	LOG_CATEGORY_RESERVED8
	LOG_CATEGORY_RESERVED9
	LOG_CATEGORY_RESERVED10
	LOG_CATEGORY_CUSTOM
)

const (
	LOG_PRIORITY_VERBOSE = iota + 1
	LOG_PRIORITY_DEBUG
	LOG_PRIORITY_INFO
	LOG_PRIORITY_WARN
	LOG_PRIORITY_ERROR
	LOG_PRIORITY_CRITICAL
	NUM_LOG_PRIORITIES
)

type LogPriority C.SDL_LogPriority

func (p LogPriority) c() C.SDL_LogPriority {
	return C.SDL_LogPriority(p)
}

func LogSetAllPriority(p LogPriority) {
	C.SDL_LogSetAllPriority(p.c())
}

func LogSetPriority(category int, p LogPriority) {
	C.SDL_LogSetPriority(C.int(category), p.c())
}

func LogGetPriority(category int) LogPriority {
	return LogPriority(C.SDL_LogGetPriority(C.int(category)))
}

func LogResetPriorities() {
	C.SDL_LogResetPriorities()
}

func Log(str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_Log(cstr)
}

func LogVerbose(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogVerbose(C.int(cat), cstr)
}

func LogDebug(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogDebug(C.int(cat), cstr)
}

func LogInfo(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogInfo(C.int(cat), cstr)
}

func LogWarn(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogWarn(C.int(cat), cstr)
}

func LogError(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogError(C.int(cat), cstr)
}

func LogCritical(cat int, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogCritical(C.int(cat), cstr)
}

func LogMessage(cat int, pri LogPriority, str string, args ...interface{}) {
	str = fmt.Sprintf(str, args...)

	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))

	C._SDL_LogMessage(C.int(cat), C.SDL_LogPriority(pri), cstr)
}

type LogOutputFunction func(data interface{}, cat int, pri LogPriority, message string)

type logOutputFunctionCtx struct {
    f LogOutputFunction
        d interface{}
}

// Yissakhar Z. Beck (DeedleFake)'s implementation
//
//export logOutputFunction
func logOutputFunction(data unsafe.Pointer, cat C.int, pri C.SDL_LogPriority, message *C.char) {
    ctx := (*logOutputFunctionCtx)(data)

    ctx.f(ctx.d, int(cat), LogPriority(pri), C.GoString(message))
}

var (
    logOutputFunctionCache LogOutputFunction
    logOutputDataCache interface{}
)

func LogGetOutputFunction() (LogOutputFunction, interface{}) {
    return logOutputFunctionCache, logOutputDataCache
}

func LogSetOutputFunction(f LogOutputFunction, data interface{}) {
    ctx := &logOutputFunctionCtx{
            f: f,
            d: data,
    }

    C.LogSetOutputFunction(unsafe.Pointer(ctx))

    logOutputFunctionCache = f
    logOutputDataCache = data
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"time"

	"github.com/AndyNortrup/GoSplunk"
)

const APP_NAME string = "TA-FitnessTrackers"
const ENFORCE_CERT_VALIDATION string = "force_cert_validation"

type FitnessInput struct {
	*splunk.ModInputConfig
	reader io.Reader //Location to read configurations from
	writer io.Writer //Location to write configurations to
}

//Write the scheme to input.writer
func (input *FitnessInput) ReturnScheme() {
	arguments := append([]splunk.Argument{}, splunk.Argument{
		Name:        ENFORCE_CERT_VALIDATION,
		Title:       "ForceCertValidation",
		Description: "If true the input requires certificate validation when making REST calls to Splunk",
		DataType:    "boolean",
	},
		splunk.Argument{
			Name:        strategyParamName,
			Title:       "FitnessService",
			Description: "Enter the name of the Fitness Service to be polled.  Options are: 'GoogleFitness', 'FitBit', 'Microsoft'",
			DataType:    "string",
		})

	scheme := &splunk.Scheme{
		Title:                 "Google Fitness",
		Description:           "Retrieves fitness data from Google Fitness.",
		UseExternalValidation: true,
		StreamingMode:         "simple",
		Args:                  arguments,
	}

	enc := xml.NewEncoder(input.writer)
	enc.Indent("   ", "   ")
	if err := enc.Encode(scheme); err != nil {
		fmt.Printf("error: %v\n", err)
	}
}

func (input *FitnessInput) ValidateScheme() (bool, string) {
	config, err := splunk.ReadModInputConfig(input.reader)
	if err != nil {
		return false, "Unable to parse configuration." + err.Error()
	}

	for _, stanza := range config.Stanzas {
		for _, param := range stanza.Params {
			//Check that the parameter STRAGEGY_PARAM_NAME is one of our defined
			// strategies for getting data
			if param.Name == strategyParamName &&
				!(param.Value == string(strategyGoogle) ||
					param.Value == strategyFitbit ||
					param.Value == strategyMicrosoft) {
				return false, "Improper service '" + param.Value + "' name indicated."
			}
		}
	}
	return true, ""
}

func (input *FitnessInput) StreamEvents() {

	config, err := splunk.ReadModInputConfig(input.reader)
	if err != nil {
		log.Printf("Unable to read Modular Input config from reader.")
	}
	input.ModInputConfig = config

	tokens, err := getUsers(splunk.LocalSplunkMgmntURL, input.SessionKey, input.getStrategy())
	if err != nil {
		log.Printf("Unable to get user tokens: %v", err)
	}

	for _, token := range tokens {
		//Create HTTP client
		clientId, clientSecret := input.getAppCredentials()
		client := getClient(&token.Token, clientId, clientSecret, input.getStrategy())

		//Get start and end points from checkpoint
		startTime, endTime := input.getTimes(input.getStrategy(), token.Name, token.UserID)

		//Create a Fitness Reader to go get the data
		fitnessReader, err := readerFactory(input.getStrategy(), startTime, endTime)
		if err != nil {
			log.Fatal(err)
		}

		input.writeCheckPoint(input.getStrategy(),
			token.Name,
			token.UserID,
			fitnessReader.getData(client, bufio.NewWriter(os.Stdout), token))
	}
}

//get the value of the strategy parameter from the configuration.
func (input *FitnessInput) getStrategy() string {
	var strategy string

	for _, stanza := range input.Stanzas {
		for _, param := range stanza.Params {
			if param.Name == strategyParamName {
				strategy = param.Value
			}
		}
	}
	if strategy == "" {
		log.Fatalf("No strategy passed to Fitness Input")
	}
	return strategy
}

// getAppCredentials makes a call to the storage/passwords enpoint and retrieves
// an appId and clinetSecret for the application.  The appId is stored in the
// password field of the endpoint data and the appId is in the username.
func (input *FitnessInput) getAppCredentials() (string, string) {
	passwords, err := splunk.GetEntities(splunk.LocalSplunkMgmntURL,
		[]string{"storage", "passwords"},
		APP_NAME,
		"nobody",
		input.SessionKey)

	if err != nil || len(passwords.Entries) == 0 {
		log.Fatalf("Unable to retrieve password entries for TA-GoogleFitness: %v\n",
			err)
	}

	for _, entry := range passwords.Entries {
		var clientId, clientSecret string
		strategyKey := false
		for _, key := range entry.Contents.Keys {
			if key.Name == "clear_password" {
				clientSecret = key.Value
			}
			if key.Name == "username" {
				clientId = key.Value
			}
			if key.Name == "realm" && key.Value == input.getStrategy() {
				strategyKey = true
			}
		}

		if strategyKey {
			return clientId, clientSecret
		}
	}
	log.Fatalf("No application credentials found for service \"%v\"", input.getStrategy())
	return "", ""
}

//getTimes returns a startTime and an endTime value.  endTime is retrived from
// a checkpoint file, if not it returns the current time.
// The end time is always the current time.
func (input *FitnessInput) getTimes(service, username, userid string) (time.Time, time.Time) {
	startTime, err := input.readCheckPoint(service, username, userid)
	if err != nil {
		startTime = time.Now()
	}
	endTime := time.Now()
	return startTime, endTime
}

func (input *FitnessInput) writeCheckPoint(service, username, userid string, t time.Time) {

	//Encode the time we've been given into bytes
	g, err := t.GobEncode()
	if err != nil {
		log.Fatalf("Unable to encode checkpoint time: %v\n", err)
	}

	//Write the checkpoint
	err = ioutil.WriteFile(input.getCheckPointPath(service, username, userid), g, 0644)
	if err != nil {
		log.Fatalf("Error writing checkpoint file: %v\n", err)
	}
}

func (input *FitnessInput) readCheckPoint(service, username, userid string) (time.Time, error) {
	b, err := ioutil.ReadFile(input.getCheckPointPath(service, username, userid))
	if err != nil {
		log.Printf("Unable to read checkpoint file:%v\n", err)
		return time.Now(), err
	}
	var t time.Time
	err = t.GobDecode(b)
	if err != nil {
		log.Printf("Unable to decode checkpoint file: %v\n", err)
		return time.Now().AddDate(0, 0, -10), err
	}
	return t, nil
}

// Takes the checkpoint dir from and config stanza name from the input and
// creates a checkpoint dir.  Should be unique for each input
func (input *FitnessInput) getCheckPointPath(service, username, userid string) string {
	//Create a hash of the stanza name as a filename
	fileName := service + "_" + username + "_" + userid
	path := path.Join(input.CheckpointDir, fileName)
	return path
}
<commit_msg>Changed the input name and description in the scheme<commit_after>package main

import (
	"bufio"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"time"

	"github.com/AndyNortrup/GoSplunk"
)

const APP_NAME string = "TA-FitnessTrackers"
const ENFORCE_CERT_VALIDATION string = "force_cert_validation"

type FitnessInput struct {
	*splunk.ModInputConfig
	reader io.Reader //Location to read configurations from
	writer io.Writer //Location to write configurations to
}

//Write the scheme to input.writer
func (input *FitnessInput) ReturnScheme() {
	arguments := append([]splunk.Argument{}, splunk.Argument{
		Name:        ENFORCE_CERT_VALIDATION,
		Title:       "ForceCertValidation",
		Description: "If true the input requires certificate validation when making REST calls to Splunk",
		DataType:    "boolean",
	},
		splunk.Argument{
			Name:        strategyParamName,
			Title:       "FitnessService",
			Description: "Enter the name of the Fitness Service to be polled.  Options are: 'GoogleFitness', 'FitBit', 'Microsoft'",
			DataType:    "string",
		})

	scheme := &splunk.Scheme{
		Title:                 "Fitness Trackers",
		Description:           "Retrieves fitness data from Google Fitness and fitbit.",
		UseExternalValidation: true,
		StreamingMode:         "simple",
		Args:                  arguments,
	}

	enc := xml.NewEncoder(input.writer)
	enc.Indent("   ", "   ")
	if err := enc.Encode(scheme); err != nil {
		fmt.Printf("error: %v\n", err)
	}
}

func (input *FitnessInput) ValidateScheme() (bool, string) {
	config, err := splunk.ReadModInputConfig(input.reader)
	if err != nil {
		return false, "Unable to parse configuration." + err.Error()
	}

	for _, stanza := range config.Stanzas {
		for _, param := range stanza.Params {
			//Check that the parameter STRAGEGY_PARAM_NAME is one of our defined
			// strategies for getting data
			if param.Name == strategyParamName &&
				!(param.Value == string(strategyGoogle) ||
					param.Value == strategyFitbit ||
					param.Value == strategyMicrosoft) {
				return false, "Improper service '" + param.Value + "' name indicated."
			}
		}
	}
	return true, ""
}

func (input *FitnessInput) StreamEvents() {

	config, err := splunk.ReadModInputConfig(input.reader)
	if err != nil {
		log.Printf("Unable to read Modular Input config from reader.")
	}
	input.ModInputConfig = config

	tokens, err := getUsers(splunk.LocalSplunkMgmntURL, input.SessionKey, input.getStrategy())
	if err != nil {
		log.Printf("Unable to get user tokens: %v", err)
	}

	for _, token := range tokens {
		//Create HTTP client
		clientId, clientSecret := input.getAppCredentials()
		client := getClient(&token.Token, clientId, clientSecret, input.getStrategy())

		//Get start and end points from checkpoint
		startTime, endTime := input.getTimes(input.getStrategy(), token.Name, token.UserID)

		//Create a Fitness Reader to go get the data
		fitnessReader, err := readerFactory(input.getStrategy(), startTime, endTime)
		if err != nil {
			log.Fatal(err)
		}

		input.writeCheckPoint(input.getStrategy(),
			token.Name,
			token.UserID,
			fitnessReader.getData(client, bufio.NewWriter(os.Stdout), token))
	}
}

//get the value of the strategy parameter from the configuration.
func (input *FitnessInput) getStrategy() string {
	var strategy string

	for _, stanza := range input.Stanzas {
		for _, param := range stanza.Params {
			if param.Name == strategyParamName {
				strategy = param.Value
			}
		}
	}
	if strategy == "" {
		log.Fatalf("No strategy passed to Fitness Input")
	}
	return strategy
}

// getAppCredentials makes a call to the storage/passwords enpoint and retrieves
// an appId and clinetSecret for the application.  The appId is stored in the
// password field of the endpoint data and the appId is in the username.
func (input *FitnessInput) getAppCredentials() (string, string) {
	passwords, err := splunk.GetEntities(splunk.LocalSplunkMgmntURL,
		[]string{"storage", "passwords"},
		APP_NAME,
		"nobody",
		input.SessionKey)

	if err != nil || len(passwords.Entries) == 0 {
		log.Fatalf("Unable to retrieve password entries for TA-GoogleFitness: %v\n",
			err)
	}

	for _, entry := range passwords.Entries {
		var clientId, clientSecret string
		strategyKey := false
		for _, key := range entry.Contents.Keys {
			if key.Name == "clear_password" {
				clientSecret = key.Value
			}
			if key.Name == "username" {
				clientId = key.Value
			}
			if key.Name == "realm" && key.Value == input.getStrategy() {
				strategyKey = true
			}
		}

		if strategyKey {
			return clientId, clientSecret
		}
	}
	log.Fatalf("No application credentials found for service \"%v\"", input.getStrategy())
	return "", ""
}

//getTimes returns a startTime and an endTime value.  endTime is retrived from
// a checkpoint file, if not it returns the current time.
// The end time is always the current time.
func (input *FitnessInput) getTimes(service, username, userid string) (time.Time, time.Time) {
	startTime, err := input.readCheckPoint(service, username, userid)
	if err != nil {
		startTime = time.Now()
	}
	endTime := time.Now()
	return startTime, endTime
}

func (input *FitnessInput) writeCheckPoint(service, username, userid string, t time.Time) {

	//Encode the time we've been given into bytes
	g, err := t.GobEncode()
	if err != nil {
		log.Fatalf("Unable to encode checkpoint time: %v\n", err)
	}

	//Write the checkpoint
	err = ioutil.WriteFile(input.getCheckPointPath(service, username, userid), g, 0644)
	if err != nil {
		log.Fatalf("Error writing checkpoint file: %v\n", err)
	}
}

func (input *FitnessInput) readCheckPoint(service, username, userid string) (time.Time, error) {
	b, err := ioutil.ReadFile(input.getCheckPointPath(service, username, userid))
	if err != nil {
		log.Printf("Unable to read checkpoint file:%v\n", err)
		return time.Now(), err
	}
	var t time.Time
	err = t.GobDecode(b)
	if err != nil {
		log.Printf("Unable to decode checkpoint file: %v\n", err)
		return time.Now().AddDate(0, 0, -10), err
	}
	return t, nil
}

// Takes the checkpoint dir from and config stanza name from the input and
// creates a checkpoint dir.  Should be unique for each input
func (input *FitnessInput) getCheckPointPath(service, username, userid string) string {
	//Create a hash of the stanza name as a filename
	fileName := service + "_" + username + "_" + userid
	path := path.Join(input.CheckpointDir, fileName)
	return path
}
<|endoftext|>