<commit_before>package core

import (
	"fmt"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"

	bstore "github.com/jbenet/go-ipfs/blocks/blockstore"
	bserv "github.com/jbenet/go-ipfs/blockservice"
	config "github.com/jbenet/go-ipfs/config"
	diag "github.com/jbenet/go-ipfs/diagnostics"
	exchange "github.com/jbenet/go-ipfs/exchange"
	bitswap "github.com/jbenet/go-ipfs/exchange/bitswap"
	bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network"
	"github.com/jbenet/go-ipfs/exchange/offline"
	mount "github.com/jbenet/go-ipfs/fuse/mount"
	merkledag "github.com/jbenet/go-ipfs/merkledag"
	namesys "github.com/jbenet/go-ipfs/namesys"
	ic "github.com/jbenet/go-ipfs/p2p/crypto"
	p2phost "github.com/jbenet/go-ipfs/p2p/host"
	p2pbhost "github.com/jbenet/go-ipfs/p2p/host/basic"
	swarm "github.com/jbenet/go-ipfs/p2p/net/swarm"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
	path "github.com/jbenet/go-ipfs/path"
	pin "github.com/jbenet/go-ipfs/pin"
	routing "github.com/jbenet/go-ipfs/routing"
	dht "github.com/jbenet/go-ipfs/routing/dht"
	ds2 "github.com/jbenet/go-ipfs/util/datastore2"
	debugerror "github.com/jbenet/go-ipfs/util/debugerror"
	eventlog "github.com/jbenet/go-ipfs/util/eventlog"
)

const IpnsValidatorTag = "ipns"
const kSizeBlockstoreWriteCache = 100

var log = eventlog.Logger("core")

// IpfsNode is IPFS Core module. It represents an IPFS instance.
type IpfsNode struct {

	// Self
	Config     *config.Config // the node's configuration
	Identity   peer.ID        // the local node's identity
	PrivateKey ic.PrivKey     // the local node's private Key
	onlineMode bool           // alternatively, offline

	// Local node
	Datastore ds2.ThreadSafeDatastoreCloser // the local datastore
	Pinning   pin.Pinner                    // the pinning manager
	Mounts    Mounts                        // current mount state, if any.

	// Services
	Peerstore   peer.Peerstore       // storage for other Peer instances
	PeerHost    p2phost.Host         // the network host (server+client)
	Routing     routing.IpfsRouting  // the routing system. recommend ipfs-dht
	Exchange    exchange.Interface   // the block exchange + strategy (bitswap)
	Blockstore  bstore.Blockstore    // the block store (lower level)
	Blocks      *bserv.BlockService  // the block service, get/add blocks.
	DAG         merkledag.DAGService // the merkle dag service, get/add objects.
	Resolver    *path.Resolver       // the path resolution system
	Namesys     namesys.NameSystem   // the name system, resolves paths to hashes
	Diagnostics *diag.Diagnostics    // the diagnostics service

	ctxgroup.ContextGroup
}

// Mounts defines what the node's mount state is. This should
// perhaps be moved to the daemon or mount. It's here because
// it needs to be accessible across daemon requests.
type Mounts struct {
	Ipfs mount.Mount
	Ipns mount.Mount
}

// NewIpfsNode constructs a new IpfsNode based on the given config.
func NewIpfsNode(ctx context.Context, cfg *config.Config, online bool) (n *IpfsNode, err error) {
	success := false // flip to true after all sub-system inits succeed
	defer func() {
		if !success && n != nil {
			n.Close()
		}
	}()

	if cfg == nil {
		return nil, debugerror.Errorf("configuration required")
	}

	n = &IpfsNode{
		onlineMode: online,
		Config:     cfg,
	}
	n.ContextGroup = ctxgroup.WithContextAndTeardown(ctx, n.teardown)
	ctx = n.ContextGroup.Context()

	// setup Peerstore
	n.Peerstore = peer.NewPeerstore()

	// setup datastore.
	if n.Datastore, err = makeDatastore(cfg.Datastore); err != nil {
		return nil, debugerror.Wrap(err)
	}

	// setup local peer ID (private key is loaded in online setup)
	if err := n.loadID(); err != nil {
		return nil, err
	}

	n.Blockstore, err = bstore.WriteCached(bstore.NewBlockstore(n.Datastore), kSizeBlockstoreWriteCache)
	if err != nil {
		return nil, debugerror.Wrap(err)
	}

	// setup online services
	if online {
		if err := n.StartOnlineServices(); err != nil {
			return nil, err // debugerror.Wraps.
		}
	} else {
		n.Exchange = offline.Exchange(n.Blockstore)
	}

	n.Blocks, err = bserv.New(n.Blockstore, n.Exchange)
	if err != nil {
		return nil, debugerror.Wrap(err)
	}

	n.DAG = merkledag.NewDAGService(n.Blocks)
	n.Pinning, err = pin.LoadPinner(n.Datastore, n.DAG)
	if err != nil {
		n.Pinning = pin.NewPinner(n.Datastore, n.DAG)
	}
	n.Resolver = &path.Resolver{DAG: n.DAG}

	success = true
	return n, nil
}

func (n *IpfsNode) StartOnlineServices() error {
	ctx := n.Context()

	if n.PeerHost != nil { // already online.
		return debugerror.New("node already online")
	}

	// load private key
	if err := n.loadPrivateKey(); err != nil {
		return err
	}

	// setup the network
	listenAddrs, err := listenAddresses(n.Config)
	if err != nil {
		return debugerror.Wrap(err)
	}
	network, err := swarm.NewNetwork(ctx, listenAddrs, n.Identity, n.Peerstore)
	if err != nil {
		return debugerror.Wrap(err)
	}
	n.AddChildGroup(network.CtxGroup())
	n.PeerHost = p2pbhost.New(network)

	// explicitly set these as our listen addrs.
	// (why not do it inside inet.NewNetwork? because this way we can
	// listen on addresses without necessarily advertising those publicly.)
	addrs, err := n.PeerHost.Network().InterfaceListenAddresses()
	if err != nil {
		return debugerror.Wrap(err)
	}
	n.Peerstore.AddAddresses(n.Identity, addrs)

	// setup diagnostics service
	n.Diagnostics = diag.NewDiagnostics(n.Identity, n.PeerHost)

	// setup routing service
	dhtRouting := dht.NewDHT(ctx, n.PeerHost, n.Datastore)
	dhtRouting.Validators[IpnsValidatorTag] = namesys.ValidateIpnsRecord
	n.Routing = dhtRouting
	n.AddChildGroup(dhtRouting)

	// setup exchange service
	const alwaysSendToPeer = true // use YesManStrategy
	bitswapNetwork := bsnet.NewFromIpfsHost(n.PeerHost, n.Routing)
	n.Exchange = bitswap.New(ctx, n.Identity, bitswapNetwork, n.Blockstore, alwaysSendToPeer)

	// setup name system
	// TODO implement an offline namesys that serves only local names.
	n.Namesys = namesys.NewNameSystem(n.Routing)

	// TODO consider moving connection supervision into the Network. We've
	// discussed improvements to this Node constructor. One improvement
	// would be to make the node configurable, allowing clients to inject
	// an Exchange, Network, or Routing component and have the constructor
	// manage the wiring. In that scenario, this dangling function is a bit
	// awkward.
	go superviseConnections(ctx, n.PeerHost, dhtRouting, n.Peerstore, n.Config.Bootstrap)
	return nil
}

func (n *IpfsNode) teardown() error {
	if err := n.Datastore.Close(); err != nil {
		return err
	}
	return nil
}

func (n *IpfsNode) OnlineMode() bool {
	return n.onlineMode
}

func (n *IpfsNode) loadID() error {
	if n.Identity != "" {
		return debugerror.New("identity already loaded")
	}

	cid := n.Config.Identity.PeerID
	if cid == "" {
		return debugerror.New("Identity was not set in config (was ipfs init run?)")
	}
	if len(cid) == 0 {
		return debugerror.New("No peer ID in config! (was ipfs init run?)")
	}

	n.Identity = peer.ID(b58.Decode(cid))
	return nil
}

func (n *IpfsNode) loadPrivateKey() error {
	if n.Identity == "" || n.Peerstore == nil {
		return debugerror.New("loaded private key out of order.")
	}

	if n.PrivateKey != nil {
		return debugerror.New("private key already loaded")
	}

	sk, err := loadPrivateKey(&n.Config.Identity, n.Identity)
	if err != nil {
		return err
	}

	n.PrivateKey = sk
	n.Peerstore.AddPrivKey(n.Identity, n.PrivateKey)
	return nil
}

func loadPrivateKey(cfg *config.Identity, id peer.ID) (ic.PrivKey, error) {
	sk, err := cfg.DecodePrivateKey("passphrase todo!")
	if err != nil {
		return nil, err
	}

	id2, err := peer.IDFromPrivateKey(sk)
	if err != nil {
		return nil, err
	}

	if id2 != id {
		return nil, fmt.Errorf("private key in config does not match id: %s != %s", id, id2)
	}

	return sk, nil
}

func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) {

	var err error
	listen := make([]ma.Multiaddr, len(cfg.Addresses.Swarm))
	for i, addr := range cfg.Addresses.Swarm {

		listen[i], err = ma.NewMultiaddr(addr)
		if err != nil {
			return nil, fmt.Errorf("Failure to parse config.Addresses.Swarm[%d]: %s", i, cfg.Addresses.Swarm)
		}
	}

	return listen, nil
}
<commit_msg>core: make sure to call swarm.FilterAddrs<commit_after>package core

import (
	"fmt"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"

	bstore "github.com/jbenet/go-ipfs/blocks/blockstore"
	bserv "github.com/jbenet/go-ipfs/blockservice"
	config "github.com/jbenet/go-ipfs/config"
	diag "github.com/jbenet/go-ipfs/diagnostics"
	exchange "github.com/jbenet/go-ipfs/exchange"
	bitswap "github.com/jbenet/go-ipfs/exchange/bitswap"
	bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network"
	"github.com/jbenet/go-ipfs/exchange/offline"
	mount "github.com/jbenet/go-ipfs/fuse/mount"
	merkledag "github.com/jbenet/go-ipfs/merkledag"
	namesys "github.com/jbenet/go-ipfs/namesys"
	ic "github.com/jbenet/go-ipfs/p2p/crypto"
	p2phost "github.com/jbenet/go-ipfs/p2p/host"
	p2pbhost "github.com/jbenet/go-ipfs/p2p/host/basic"
	swarm "github.com/jbenet/go-ipfs/p2p/net/swarm"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
	path "github.com/jbenet/go-ipfs/path"
	pin "github.com/jbenet/go-ipfs/pin"
	routing "github.com/jbenet/go-ipfs/routing"
	dht "github.com/jbenet/go-ipfs/routing/dht"
	ds2 "github.com/jbenet/go-ipfs/util/datastore2"
	debugerror "github.com/jbenet/go-ipfs/util/debugerror"
	eventlog "github.com/jbenet/go-ipfs/util/eventlog"
)

const IpnsValidatorTag = "ipns"
const kSizeBlockstoreWriteCache = 100

var log = eventlog.Logger("core")

// IpfsNode is IPFS Core module. It represents an IPFS instance.
type IpfsNode struct {

	// Self
	Config     *config.Config // the node's configuration
	Identity   peer.ID        // the local node's identity
	PrivateKey ic.PrivKey     // the local node's private Key
	onlineMode bool           // alternatively, offline

	// Local node
	Datastore ds2.ThreadSafeDatastoreCloser // the local datastore
	Pinning   pin.Pinner                    // the pinning manager
	Mounts    Mounts                        // current mount state, if any.

	// Services
	Peerstore   peer.Peerstore       // storage for other Peer instances
	PeerHost    p2phost.Host         // the network host (server+client)
	Routing     routing.IpfsRouting  // the routing system. recommend ipfs-dht
	Exchange    exchange.Interface   // the block exchange + strategy (bitswap)
	Blockstore  bstore.Blockstore    // the block store (lower level)
	Blocks      *bserv.BlockService  // the block service, get/add blocks.
	DAG         merkledag.DAGService // the merkle dag service, get/add objects.
	Resolver    *path.Resolver       // the path resolution system
	Namesys     namesys.NameSystem   // the name system, resolves paths to hashes
	Diagnostics *diag.Diagnostics    // the diagnostics service

	ctxgroup.ContextGroup
}

// Mounts defines what the node's mount state is. This should
// perhaps be moved to the daemon or mount. It's here because
// it needs to be accessible across daemon requests.
type Mounts struct {
	Ipfs mount.Mount
	Ipns mount.Mount
}

// NewIpfsNode constructs a new IpfsNode based on the given config.
func NewIpfsNode(ctx context.Context, cfg *config.Config, online bool) (n *IpfsNode, err error) {
	success := false // flip to true after all sub-system inits succeed
	defer func() {
		if !success && n != nil {
			n.Close()
		}
	}()

	if cfg == nil {
		return nil, debugerror.Errorf("configuration required")
	}

	n = &IpfsNode{
		onlineMode: online,
		Config:     cfg,
	}
	n.ContextGroup = ctxgroup.WithContextAndTeardown(ctx, n.teardown)
	ctx = n.ContextGroup.Context()

	// setup Peerstore
	n.Peerstore = peer.NewPeerstore()

	// setup datastore.
	if n.Datastore, err = makeDatastore(cfg.Datastore); err != nil {
		return nil, debugerror.Wrap(err)
	}

	// setup local peer ID (private key is loaded in online setup)
	if err := n.loadID(); err != nil {
		return nil, err
	}

	n.Blockstore, err = bstore.WriteCached(bstore.NewBlockstore(n.Datastore), kSizeBlockstoreWriteCache)
	if err != nil {
		return nil, debugerror.Wrap(err)
	}

	// setup online services
	if online {
		if err := n.StartOnlineServices(); err != nil {
			return nil, err // debugerror.Wraps.
		}
	} else {
		n.Exchange = offline.Exchange(n.Blockstore)
	}

	n.Blocks, err = bserv.New(n.Blockstore, n.Exchange)
	if err != nil {
		return nil, debugerror.Wrap(err)
	}

	n.DAG = merkledag.NewDAGService(n.Blocks)
	n.Pinning, err = pin.LoadPinner(n.Datastore, n.DAG)
	if err != nil {
		n.Pinning = pin.NewPinner(n.Datastore, n.DAG)
	}
	n.Resolver = &path.Resolver{DAG: n.DAG}

	success = true
	return n, nil
}

func (n *IpfsNode) StartOnlineServices() error {
	ctx := n.Context()

	if n.PeerHost != nil { // already online.
		return debugerror.New("node already online")
	}

	// load private key
	if err := n.loadPrivateKey(); err != nil {
		return err
	}

	if err := n.startNetwork(); err != nil {
		return err
	}

	// setup diagnostics service
	n.Diagnostics = diag.NewDiagnostics(n.Identity, n.PeerHost)

	// setup routing service
	dhtRouting := dht.NewDHT(ctx, n.PeerHost, n.Datastore)
	dhtRouting.Validators[IpnsValidatorTag] = namesys.ValidateIpnsRecord
	n.Routing = dhtRouting
	n.AddChildGroup(dhtRouting)

	// setup exchange service
	const alwaysSendToPeer = true // use YesManStrategy
	bitswapNetwork := bsnet.NewFromIpfsHost(n.PeerHost, n.Routing)
	n.Exchange = bitswap.New(ctx, n.Identity, bitswapNetwork, n.Blockstore, alwaysSendToPeer)

	// setup name system
	// TODO implement an offline namesys that serves only local names.
	n.Namesys = namesys.NewNameSystem(n.Routing)

	// TODO consider moving connection supervision into the Network. We've
	// discussed improvements to this Node constructor. One improvement
	// would be to make the node configurable, allowing clients to inject
	// an Exchange, Network, or Routing component and have the constructor
	// manage the wiring. In that scenario, this dangling function is a bit
	// awkward.
	go superviseConnections(ctx, n.PeerHost, dhtRouting, n.Peerstore, n.Config.Bootstrap)
	return nil
}

func (n *IpfsNode) startNetwork() error {
	ctx := n.Context()

	// setup the network
	listenAddrs, err := listenAddresses(n.Config)
	if err != nil {
		return debugerror.Wrap(err)
	}
	// make sure we dont error out if our config includes some addresses we cant use.
	listenAddrs = swarm.FilterAddrs(listenAddrs)
	network, err := swarm.NewNetwork(ctx, listenAddrs, n.Identity, n.Peerstore)
	if err != nil {
		return debugerror.Wrap(err)
	}
	n.AddChildGroup(network.CtxGroup())
	n.PeerHost = p2pbhost.New(network)

	// explicitly set these as our listen addrs.
	// (why not do it inside inet.NewNetwork? because this way we can
	// listen on addresses without necessarily advertising those publicly.)
	addrs, err := n.PeerHost.Network().InterfaceListenAddresses()
	if err != nil {
		return debugerror.Wrap(err)
	}
	n.Peerstore.AddAddresses(n.Identity, addrs)
	return nil
}

func (n *IpfsNode) teardown() error {
	if err := n.Datastore.Close(); err != nil {
		return err
	}
	return nil
}

func (n *IpfsNode) OnlineMode() bool {
	return n.onlineMode
}

func (n *IpfsNode) loadID() error {
	if n.Identity != "" {
		return debugerror.New("identity already loaded")
	}

	cid := n.Config.Identity.PeerID
	if cid == "" {
		return debugerror.New("Identity was not set in config (was ipfs init run?)")
	}
	if len(cid) == 0 {
		return debugerror.New("No peer ID in config! (was ipfs init run?)")
	}

	n.Identity = peer.ID(b58.Decode(cid))
	return nil
}

func (n *IpfsNode) loadPrivateKey() error {
	if n.Identity == "" || n.Peerstore == nil {
		return debugerror.New("loaded private key out of order.")
	}

	if n.PrivateKey != nil {
		return debugerror.New("private key already loaded")
	}

	sk, err := loadPrivateKey(&n.Config.Identity, n.Identity)
	if err != nil {
		return err
	}

	n.PrivateKey = sk
	n.Peerstore.AddPrivKey(n.Identity, n.PrivateKey)
	return nil
}

func loadPrivateKey(cfg *config.Identity, id peer.ID) (ic.PrivKey, error) {
	sk, err := cfg.DecodePrivateKey("passphrase todo!")
	if err != nil {
		return nil, err
	}

	id2, err := peer.IDFromPrivateKey(sk)
	if err != nil {
		return nil, err
	}

	if id2 != id {
		return nil, fmt.Errorf("private key in config does not match id: %s != %s", id, id2)
	}

	return sk, nil
}

func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) {

	var err error
	listen := make([]ma.Multiaddr, len(cfg.Addresses.Swarm))
	for i, addr := range cfg.Addresses.Swarm {

		listen[i], err = ma.NewMultiaddr(addr)
		if err != nil {
			return nil, fmt.Errorf("Failure to parse config.Addresses.Swarm[%d]: %s", i, cfg.Addresses.Swarm)
		}
	}

	return listen, nil
}
<|endoftext|>


<commit_before>package core

import (
	"context"
	"encoding/json"
	"expvar"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"chain/core/fetch"
	"chain/core/leader"
	"chain/core/mockhsm"
	"chain/core/txdb"
	"chain/crypto/ed25519"
	"chain/crypto/ed25519/chainkd"
	"chain/database/pg"
	"chain/database/sql"
	"chain/errors"
	"chain/log"
	"chain/net/http/httpjson"
	"chain/net/rpc"
	"chain/protocol"
	"chain/protocol/bc"
	"chain/protocol/state"
)

var (
	errAlreadyConfigured = errors.New("core is already configured; must reset first")
	errUnconfigured      = errors.New("core is not configured")
	errBadGenerator      = errors.New("generator returned an unsuccessful response")
	errBadBlockXPub      = errors.New("supplied block xpub is invalid")
	errNoClientTokens    = errors.New("cannot enable client auth without client access tokens")
	errBadSignerURL      = errors.New("block signer URL is invalid")
	errBadSignerPubkey   = errors.New("block signer pubkey is invalid")
	errBadQuorum         = errors.New("quorum must be greater than 0 if there are signers")
	// errProdReset is returned when reset is called on a
	// production system.
	errProdReset = errors.New("reset called on production system")
)

// reserved mockhsm key alias
const (
	networkRPCVersion = 1
	autoBlockKeyAlias = "_CHAIN_CORE_AUTO_BLOCK_KEY"
)

func isProduction() bool {
	bt := expvar.Get("buildtag")
	return bt != nil && bt.String() != `"dev"`
}

// Schema returns DDL for the entire Chain Core Postgres schema.
func Schema() string {
	return files["schema.sql"]
}

func (a *api) reset(ctx context.Context) error {
	if isProduction() {
		return errors.Wrap(errProdReset)
	}

	closeConnOK(httpjson.ResponseWriter(ctx), httpjson.Request(ctx))
	execSelf("RESET=true")
	panic("unreached")
}

func (a *api) info(ctx context.Context) (map[string]interface{}, error) {
	if a.config == nil {
		// never configured
		return map[string]interface{}{
			"is_configured": false,
		}, nil
	}
	if leader.IsLeading() {
		return a.leaderInfo(ctx)
	} else {
		var resp map[string]interface{}
		err := callLeader(ctx, "/info", nil, &resp)
		return resp, err
	}
}

func (a *api) leaderInfo(ctx context.Context) (map[string]interface{}, error) {
	localHeight := a.c.Height()
	var (
		generatorHeight  uint64
		generatorFetched time.Time
	)
	if a.config.IsGenerator {
		generatorHeight = localHeight
		generatorFetched = time.Now()
	} else {
		generatorHeight, generatorFetched = fetch.GeneratorHeight()
	}

	buildCommit := json.RawMessage(expvar.Get("buildcommit").String())
	buildDate := json.RawMessage(expvar.Get("builddate").String())

	// Because everything is asynchronous, it's possible for the localHeight to
	// be higher than our cached generator height. In that case, display the
	// generatorHeight as our height.
	if localHeight > generatorHeight {
		generatorHeight = localHeight
	}

	return map[string]interface{}{
		"is_configured":                     true,
		"configured_at":                     a.config.ConfiguredAt,
		"is_signer":                         a.config.IsSigner,
		"is_generator":                      a.config.IsGenerator,
		"generator_url":                     a.config.GeneratorURL,
		"generator_access_token":            obfuscateTokenSecret(a.config.GeneratorAccessToken),
		"blockchain_id":                     a.config.BlockchainID,
		"block_height":                      localHeight,
		"generator_block_height":            generatorHeight,
		"generator_block_height_fetched_at": generatorFetched,
		"is_production":                     isProduction(),
		"network_rpc_version":               networkRPCVersion,
		"build_commit":                      &buildCommit,
		"build_date":                        &buildDate,
	}, nil
}

// Configure configures the core by writing to the database.
// If running in a cored process,
// the caller must ensure that the new configuration is properly reloaded,
// for example by restarting the process.
//
// If c.IsSigner is true, Configure generates a new mockhsm keypair
// for signing blocks, and assigns it to c.BlockXPub.
//
// If c.IsGenerator is true, Configure creates an initial block,
// saves it, and assigns its hash to c.BlockchainID.
// Otherwise, c.IsGenerator is false, and Configure makes a test request
// to GeneratorURL to detect simple configuration mistakes.
func Configure(ctx context.Context, db pg.DB, c *Config) error {
	var err error
	if !c.IsGenerator {
		err = tryGenerator(
			ctx,
			c.GeneratorURL,
			c.GeneratorAccessToken,
			c.BlockchainID.String(),
		)
		if err != nil {
			return err
		}
	}

	var signingKeys []ed25519.PublicKey
	if c.IsSigner {
		var blockXPub chainkd.XPub
		if c.BlockXPub == "" {
			hsm := mockhsm.New(db)
			coreXPub, created, err := hsm.GetOrCreateKey(ctx, autoBlockKeyAlias)
			if err != nil {
				return err
			}
			blockXPub = coreXPub.XPub
			if created {
				log.Messagef(ctx, "Generated new block-signing key %s\n", blockXPub.String())
			} else {
				log.Messagef(ctx, "Using block-signing key %s\n", blockXPub.String())
			}
			c.BlockXPub = blockXPub.String()
		} else {
			var blockXPub chainkd.XPub
			err = blockXPub.UnmarshalText([]byte(c.BlockXPub))
			if err != nil {
				return errors.Wrap(errBadBlockXPub, err.Error())
			}
		}
		signingKeys = append(signingKeys, blockXPub.PublicKey())
	}

	if c.IsGenerator {
		for _, signer := range c.Signers {
			_, err = url.Parse(signer.URL)
			if err != nil {
				return errors.Wrap(errBadSignerURL, err.Error())
			}
			signingKey, err := chainkd.NewEd25519PublicKey(signer.Pubkey)
			if err != nil {
				return errors.Wrap(errBadSignerPubkey, err.Error())
			}
			signingKeys = append(signingKeys, signingKey)
		}

		if c.Quorum == 0 && len(signingKeys) > 0 {
			return errors.Wrap(errBadQuorum)
		}

		block, err := protocol.NewInitialBlock(signingKeys, c.Quorum, time.Now())
		if err != nil {
			return err
		}
		store, pool := txdb.New(db.(*sql.DB))
		chain, err := protocol.NewChain(ctx, store, pool, nil)
		if err != nil {
			return err
		}

		err = chain.CommitBlock(ctx, block, state.Empty())
		if err != nil {
			return err
		}

		c.BlockchainID = block.Hash()
		chain.MaxIssuanceWindow = c.MaxIssuanceWindow
	}

	var blockSignerData []byte
	if len(c.Signers) > 0 {
		blockSignerData, err = json.Marshal(c.Signers)
		if err != nil {
			return errors.Wrap(err)
		}
	}

	const q = `
		INSERT INTO config (is_signer, block_xpub, is_generator,
			blockchain_id, generator_url, generator_access_token,
			remote_block_signers, max_issuance_window_ms, configured_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW())
	`
	_, err = db.Exec(
		ctx,
		q,
		c.IsSigner,
		c.BlockXPub,
		c.IsGenerator,
		c.BlockchainID,
		c.GeneratorURL,
		c.GeneratorAccessToken,
		blockSignerData,
		bc.DurationMillis(c.MaxIssuanceWindow),
	)
	return err
}

func (a *api) configure(ctx context.Context, x *Config) error {
	if a.config != nil {
		return errAlreadyConfigured
	}

	err := Configure(ctx, pg.FromContext(ctx), x)
	if err != nil {
		return err
	}

	closeConnOK(httpjson.ResponseWriter(ctx), httpjson.Request(ctx))
	execSelf()
	panic("unreached")
}

// LoadConfig loads the stored configuration, if any, from the database.
func LoadConfig(ctx context.Context, db pg.DB) (*Config, error) {
	const q = `
			SELECT is_signer, is_generator,
			blockchain_id, generator_url, generator_access_token, block_xpub,
			remote_block_signers, max_issuance_window_ms, configured_at
			FROM config
		`

	c := new(Config)
	var (
		blockSignerData []byte
		miw             int64
	)
	err := db.QueryRow(ctx, q).Scan(
		&c.IsSigner,
		&c.IsGenerator,
		&c.BlockchainID,
		&c.GeneratorURL,
		&c.GeneratorAccessToken,
		&c.BlockXPub,
		&blockSignerData,
		&miw,
		&c.ConfiguredAt,
	)
	if err == sql.ErrNoRows {
		return nil, nil
	} else if err != nil {
		return nil, errors.Wrap(err, "fetching Core config")
	}

	if len(blockSignerData) > 0 {
		err = json.Unmarshal(blockSignerData, &c.Signers)
		if err != nil {
			return nil, errors.Wrap(err)
		}
	}

	c.MaxIssuanceWindow = time.Duration(miw) * time.Millisecond
	return c, nil
}

func tryGenerator(ctx context.Context, url, accessToken, blockchainID string) error {
	client := &rpc.Client{
		BaseURL:      url,
		AccessToken:  accessToken,
		BlockchainID: blockchainID,
	}
	var x struct {
		BlockHeight uint64 `json:"block_height"`
	}
	err := client.Call(ctx, "/rpc/block-height", nil, &x)
	if err != nil {
		return errors.Wrap(errBadGenerator, err.Error())
	}

	if x.BlockHeight < 1 {
		return errBadGenerator
	}

	return nil
}

func closeConnOK(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Connection", "close")
	w.WriteHeader(http.StatusNoContent)

	hijacker, ok := w.(http.Hijacker)
	if !ok {
		log.Messagef(req.Context(), "no hijacker")
		return
	}
	conn, buf, err := hijacker.Hijack()
	if err != nil {
		log.Messagef(req.Context(), "could not hijack connection: %s\n", err)
		return
	}
	err = buf.Flush()
	if err != nil {
		log.Messagef(req.Context(), "could not flush connection buffer: %s\n", err)
	}
	err = conn.Close()
	if err != nil {
		log.Messagef(req.Context(), "could not close connection: %s\n", err)
	}
}

// execSelf execs Args with environment values replaced
// by the ones in env.
func execSelf(env ...string) {
	binpath, err := exec.LookPath(os.Args[0])
	if err != nil {
		panic(err)
	}

	env = mergeEnvLists(env, os.Environ())
	err = syscall.Exec(binpath, os.Args, env)
	if err != nil {
		panic(err)
	}
}

// mergeEnvLists merges the two environment lists such that
// variables with the same name in "in" replace those in "out".
// This always returns a newly allocated slice.
func mergeEnvLists(in, out []string) []string {
	out = append([]string(nil), out...)
NextVar:
	for _, inkv := range in {
		k := strings.SplitAfterN(inkv, "=", 2)[0]
		for i, outkv := range out {
			if strings.HasPrefix(outkv, k) {
				out[i] = inkv
				continue NextVar
			}
		}
		out = append(out, inkv)
	}
	return out
}

func obfuscateTokenSecret(token string) string {
	toks := strings.SplitN(token, ":", 2)
	var res string
	if len(toks) > 0 {
		res += toks[0]
	}
	if len(toks) > 1 {
		res += ":********"
	}
	return res
}
<commit_msg>core: set default MaxIssuanceWindow when configuring from api<commit_after>package core

import (
	"context"
	"encoding/json"
	"expvar"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"chain/core/fetch"
	"chain/core/leader"
	"chain/core/mockhsm"
	"chain/core/txdb"
	"chain/crypto/ed25519"
	"chain/crypto/ed25519/chainkd"
	"chain/database/pg"
	"chain/database/sql"
	"chain/errors"
	"chain/log"
	"chain/net/http/httpjson"
	"chain/net/rpc"
	"chain/protocol"
	"chain/protocol/bc"
	"chain/protocol/state"
)

var (
	errAlreadyConfigured = errors.New("core is already configured; must reset first")
	errUnconfigured      = errors.New("core is not configured")
	errBadGenerator      = errors.New("generator returned an unsuccessful response")
	errBadBlockXPub      = errors.New("supplied block xpub is invalid")
	errNoClientTokens    = errors.New("cannot enable client auth without client access tokens")
	errBadSignerURL      = errors.New("block signer URL is invalid")
	errBadSignerPubkey   = errors.New("block signer pubkey is invalid")
	errBadQuorum         = errors.New("quorum must be greater than 0 if there are signers")
	// errProdReset is returned when reset is called on a
	// production system.
	errProdReset = errors.New("reset called on production system")
)

// reserved mockhsm key alias
const (
	networkRPCVersion = 1
	autoBlockKeyAlias = "_CHAIN_CORE_AUTO_BLOCK_KEY"
)

func isProduction() bool {
	bt := expvar.Get("buildtag")
	return bt != nil && bt.String() != `"dev"`
}

// Schema returns DDL for the entire Chain Core Postgres schema.
func Schema() string {
	return files["schema.sql"]
}

func (a *api) reset(ctx context.Context) error {
	if isProduction() {
		return errors.Wrap(errProdReset)
	}

	closeConnOK(httpjson.ResponseWriter(ctx), httpjson.Request(ctx))
	execSelf("RESET=true")
	panic("unreached")
}

func (a *api) info(ctx context.Context) (map[string]interface{}, error) {
	if a.config == nil {
		// never configured
		return map[string]interface{}{
			"is_configured": false,
		}, nil
	}
	if leader.IsLeading() {
		return a.leaderInfo(ctx)
	} else {
		var resp map[string]interface{}
		err := callLeader(ctx, "/info", nil, &resp)
		return resp, err
	}
}

func (a *api) leaderInfo(ctx context.Context) (map[string]interface{}, error) {
	localHeight := a.c.Height()
	var (
		generatorHeight  uint64
		generatorFetched time.Time
	)
	if a.config.IsGenerator {
		generatorHeight = localHeight
		generatorFetched = time.Now()
	} else {
		generatorHeight, generatorFetched = fetch.GeneratorHeight()
	}

	buildCommit := json.RawMessage(expvar.Get("buildcommit").String())
	buildDate := json.RawMessage(expvar.Get("builddate").String())

	// Because everything is asynchronous, it's possible for the localHeight to
	// be higher than our cached generator height. In that case, display the
	// generatorHeight as our height.
	if localHeight > generatorHeight {
		generatorHeight = localHeight
	}

	return map[string]interface{}{
		"is_configured":                     true,
		"configured_at":                     a.config.ConfiguredAt,
		"is_signer":                         a.config.IsSigner,
		"is_generator":                      a.config.IsGenerator,
		"generator_url":                     a.config.GeneratorURL,
		"generator_access_token":            obfuscateTokenSecret(a.config.GeneratorAccessToken),
		"blockchain_id":                     a.config.BlockchainID,
		"block_height":                      localHeight,
		"generator_block_height":            generatorHeight,
		"generator_block_height_fetched_at": generatorFetched,
		"is_production":                     isProduction(),
		"network_rpc_version":               networkRPCVersion,
		"build_commit":                      &buildCommit,
		"build_date":                        &buildDate,
	}, nil
}

// Configure configures the core by writing to the database.
// If running in a cored process,
// the caller must ensure that the new configuration is properly reloaded,
// for example by restarting the process.
//
// If c.IsSigner is true, Configure generates a new mockhsm keypair
// for signing blocks, and assigns it to c.BlockXPub.
//
// If c.IsGenerator is true, Configure creates an initial block,
// saves it, and assigns its hash to c.BlockchainID.
// Otherwise, c.IsGenerator is false, and Configure makes a test request
// to GeneratorURL to detect simple configuration mistakes.
func Configure(ctx context.Context, db pg.DB, c *Config) error {
	var err error
	if !c.IsGenerator {
		err = tryGenerator(
			ctx,
			c.GeneratorURL,
			c.GeneratorAccessToken,
			c.BlockchainID.String(),
		)
		if err != nil {
			return err
		}
	}

	var signingKeys []ed25519.PublicKey
	if c.IsSigner {
		var blockXPub chainkd.XPub
		if c.BlockXPub == "" {
			hsm := mockhsm.New(db)
			coreXPub, created, err := hsm.GetOrCreateKey(ctx, autoBlockKeyAlias)
			if err != nil {
				return err
			}
			blockXPub = coreXPub.XPub
			if created {
				log.Messagef(ctx, "Generated new block-signing key %s\n", blockXPub.String())
			} else {
				log.Messagef(ctx, "Using block-signing key %s\n", blockXPub.String())
			}
			c.BlockXPub = blockXPub.String()
		} else {
			var blockXPub chainkd.XPub
			err = blockXPub.UnmarshalText([]byte(c.BlockXPub))
			if err != nil {
				return errors.Wrap(errBadBlockXPub, err.Error())
			}
		}
		signingKeys = append(signingKeys, blockXPub.PublicKey())
	}

	if c.IsGenerator {
		for _, signer := range c.Signers {
			_, err = url.Parse(signer.URL)
			if err != nil {
				return errors.Wrap(errBadSignerURL, err.Error())
			}
			signingKey, err := chainkd.NewEd25519PublicKey(signer.Pubkey)
			if err != nil {
				return errors.Wrap(errBadSignerPubkey, err.Error())
			}
			signingKeys = append(signingKeys, signingKey)
		}

		if c.Quorum == 0 && len(signingKeys) > 0 {
			return errors.Wrap(errBadQuorum)
		}

		block, err := protocol.NewInitialBlock(signingKeys, c.Quorum, time.Now())
		if err != nil {
			return err
		}
		store, pool := txdb.New(db.(*sql.DB))
		chain, err := protocol.NewChain(ctx, store, pool, nil)
		if err != nil {
			return err
		}

		err = chain.CommitBlock(ctx, block, state.Empty())
		if err != nil {
			return err
		}

		c.BlockchainID = block.Hash()
		chain.MaxIssuanceWindow = c.MaxIssuanceWindow
	}

	var blockSignerData []byte
	if len(c.Signers) > 0 {
		blockSignerData, err = json.Marshal(c.Signers)
		if err != nil {
			return errors.Wrap(err)
		}
	}

	const q = `
		INSERT INTO config (is_signer, block_xpub, is_generator,
			blockchain_id, generator_url, generator_access_token,
			remote_block_signers, max_issuance_window_ms, configured_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW())
	`
	_, err = db.Exec(
		ctx,
		q,
		c.IsSigner,
		c.BlockXPub,
		c.IsGenerator,
		c.BlockchainID,
		c.GeneratorURL,
		c.GeneratorAccessToken,
		blockSignerData,
		bc.DurationMillis(c.MaxIssuanceWindow),
	)
	return err
}

func (a *api) configure(ctx context.Context, x *Config) error {
	if a.config != nil {
		return errAlreadyConfigured
	}

	if x.IsGenerator && x.MaxIssuanceWindow == 0 {
		x.MaxIssuanceWindow = 24 * time.Hour
	}

	err := Configure(ctx, pg.FromContext(ctx), x)
	if err != nil {
		return err
	}

	closeConnOK(httpjson.ResponseWriter(ctx), httpjson.Request(ctx))
	execSelf()
	panic("unreached")
}

// LoadConfig loads the stored configuration, if any, from the database.
func LoadConfig(ctx context.Context, db pg.DB) (*Config, error) {
	const q = `
			SELECT is_signer, is_generator,
			blockchain_id, generator_url, generator_access_token, block_xpub,
			remote_block_signers, max_issuance_window_ms, configured_at
			FROM config
		`

	c := new(Config)
	var (
		blockSignerData []byte
		miw             int64
	)
	err := db.QueryRow(ctx, q).Scan(
		&c.IsSigner,
		&c.IsGenerator,
		&c.BlockchainID,
		&c.GeneratorURL,
		&c.GeneratorAccessToken,
		&c.BlockXPub,
		&blockSignerData,
		&miw,
		&c.ConfiguredAt,
	)
	if err == sql.ErrNoRows {
		return nil, nil
	} else if err != nil {
		return nil, errors.Wrap(err, "fetching Core config")
	}

	if len(blockSignerData) > 0 {
		err = json.Unmarshal(blockSignerData, &c.Signers)
		if err != nil {
			return nil, errors.Wrap(err)
		}
	}

	c.MaxIssuanceWindow = time.Duration(miw) * time.Millisecond
	return c, nil
}

func tryGenerator(ctx context.Context, url, accessToken, blockchainID string) error {
	client := &rpc.Client{
		BaseURL:      url,
		AccessToken:  accessToken,
		BlockchainID: blockchainID,
	}
	var x struct {
		BlockHeight uint64 `json:"block_height"`
	}
	err := client.Call(ctx, "/rpc/block-height", nil, &x)
	if err != nil {
		return errors.Wrap(errBadGenerator, err.Error())
	}

	if x.BlockHeight < 1 {
		return errBadGenerator
	}

	return nil
}

func closeConnOK(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Connection", "close")
	w.WriteHeader(http.StatusNoContent)

	hijacker, ok := w.(http.Hijacker)
	if !ok {
		log.Messagef(req.Context(), "no hijacker")
		return
	}
	conn, buf, err := hijacker.Hijack()
	if err != nil {
		log.Messagef(req.Context(), "could not hijack connection: %s\n", err)
		return
	}
	err = buf.Flush()
	if err != nil {
		log.Messagef(req.Context(), "could not flush connection buffer: %s\n", err)
	}
	err = conn.Close()
	if err != nil {
		log.Messagef(req.Context(), "could not close connection: %s\n", err)
	}
}

// execSelf execs Args with environment values replaced
// by the ones in env.
func execSelf(env ...string) {
	binpath, err := exec.LookPath(os.Args[0])
	if err != nil {
		panic(err)
	}

	env = mergeEnvLists(env, os.Environ())
	err = syscall.Exec(binpath, os.Args, env)
	if err != nil {
		panic(err)
	}
}

// mergeEnvLists merges the two environment lists such that
// variables with the same name in "in" replace those in "out".
// This always returns a newly allocated slice.
func mergeEnvLists(in, out []string) []string {
	out = append([]string(nil), out...)
NextVar:
	for _, inkv := range in {
		k := strings.SplitAfterN(inkv, "=", 2)[0]
		for i, outkv := range out {
			if strings.HasPrefix(outkv, k) {
				out[i] = inkv
				continue NextVar
			}
		}
		out = append(out, inkv)
	}
	return out
}

func obfuscateTokenSecret(token string) string {
	toks := strings.SplitN(token, ":", 2)
	var res string
	if len(toks) > 0 {
		res += toks[0]
	}
	if len(toks) > 1 {
		res += ":********"
	}
	return res
}
<|endoftext|>


<commit_before><commit_msg>Add play_random_track sample<commit_after><|endoftext|>


<commit_before>package cpu

import (
	"fmt"
	"time"

	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/plugins/inputs"
	"github.com/influxdata/telegraf/plugins/inputs/system"
	"github.com/shirou/gopsutil/cpu"
)

type CPUStats struct {
	ps        system.PS
	lastStats map[string]cpu.TimesStat

	PerCPU         bool `toml:"percpu"`
	TotalCPU       bool `toml:"totalcpu"`
	CollectCPUTime bool `toml:"collect_cpu_time"`
	ReportActive   bool `toml:"report_active"`
}

func NewCPUStats(ps system.PS) *CPUStats {
	return &CPUStats{
		ps:             ps,
		CollectCPUTime: true,
		ReportActive:   true,
	}
}

func (_ *CPUStats) Description() string {
	return "Read metrics about cpu usage"
}

var sampleConfig = `
  ## Whether to report per-cpu stats or not
  percpu = true
  ## Whether to report total system cpu stats or not
  totalcpu = true
  ## If true, collect raw CPU time metrics.
  collect_cpu_time = false
  ## If true, compute and report the sum of all non-idle CPU states.
  report_active = false
`

func (_ *CPUStats) SampleConfig() string {
	return sampleConfig
}

func (s *CPUStats) Gather(acc telegraf.Accumulator) error {
	times, err := s.ps.CPUTimes(s.PerCPU, s.TotalCPU)
	if err != nil {
		return fmt.Errorf("error getting CPU info: %s", err)
	}
	now := time.Now()

	for _, cts := range times {
		tags := map[string]string{
			"cpu": cts.CPU,
		}

		total := totalCpuTime(cts)
		active := activeCpuTime(cts)

		if s.CollectCPUTime {
			// Add cpu time metrics
			fieldsC := map[string]interface{}{
				"time_user":       cts.User,
				"time_system":     cts.System,
				"time_idle":       cts.Idle,
				"time_nice":       cts.Nice,
				"time_iowait":     cts.Iowait,
				"time_irq":        cts.Irq,
				"time_softirq":    cts.Softirq,
				"time_steal":      cts.Steal,
				"time_guest":      cts.Guest,
				"time_guest_nice": cts.GuestNice,
			}
			if s.ReportActive {
				fieldsC["time_active"] = activeCpuTime(cts)
			}
			acc.AddCounter("cpu", fieldsC, tags, now)
		}

		// Add in percentage
		if len(s.lastStats) == 0 {
			// If it's the 1st gather, can't get CPU Usage stats yet
			continue
		}

		lastCts, ok := s.lastStats[cts.CPU]
		if !ok {
			continue
		}
		lastTotal := totalCpuTime(lastCts)
		lastActive := activeCpuTime(lastCts)
		totalDelta := total - lastTotal

		if totalDelta < 0 {
			err = fmt.Errorf("Error: current total CPU time is less than previous total CPU time")
			break
		}

		if totalDelta == 0 {
			continue
		}

		fieldsG := map[string]interface{}{
			"usage_user":       100 * (cts.User - lastCts.User - (cts.Guest - lastCts.Guest)) / totalDelta,
			"usage_system":     100 * (cts.System - lastCts.System) / totalDelta,
			"usage_idle":       100 * (cts.Idle - lastCts.Idle) / totalDelta,
			"usage_nice":       100 * (cts.Nice - lastCts.Nice - (cts.GuestNice - lastCts.GuestNice)) / totalDelta,
			"usage_iowait":     100 * (cts.Iowait - lastCts.Iowait) / totalDelta,
			"usage_irq":        100 * (cts.Irq - lastCts.Irq) / totalDelta,
			"usage_softirq":    100 * (cts.Softirq - lastCts.Softirq) / totalDelta,
			"usage_steal":      100 * (cts.Steal - lastCts.Steal) / totalDelta,
			"usage_guest":      100 * (cts.Guest - lastCts.Guest) / totalDelta,
			"usage_guest_nice": 100 * (cts.GuestNice - lastCts.GuestNice) / totalDelta,
		}
		if s.ReportActive {
			fieldsG["usage_active"] = 100 * (active - lastActive) / totalDelta
		}
		acc.AddGauge("cpu", fieldsG, tags, now)
	}

	s.lastStats = make(map[string]cpu.TimesStat)
	for _, cts := range times {
		s.lastStats[cts.CPU] = cts
	}

	return err
}

func totalCpuTime(t cpu.TimesStat) float64 {
	total := t.User + t.System + t.Nice + t.Iowait + t.Irq + t.Softirq + t.Steal +
		t.Idle
	return total
}

func activeCpuTime(t cpu.TimesStat) float64 {
	active := totalCpuTime(t) - t.Idle
	return active
}

func init() {
	inputs.Add("cpu", func() telegraf.Input {
		return &CPUStats{
			PerCPU:   true,
			TotalCPU: true,
			ps:       system.NewSystemPS(),
		}
	})
}
<commit_msg>Unify comments style in the CPU input (#8605)<commit_after>package cpu

import (
	"fmt"
	"time"

	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/plugins/inputs"
	"github.com/influxdata/telegraf/plugins/inputs/system"
	"github.com/shirou/gopsutil/cpu"
)

type CPUStats struct {
	ps        system.PS
	lastStats map[string]cpu.TimesStat

	PerCPU         bool `toml:"percpu"`
	TotalCPU       bool `toml:"totalcpu"`
	CollectCPUTime bool `toml:"collect_cpu_time"`
	ReportActive   bool `toml:"report_active"`
}

func NewCPUStats(ps system.PS) *CPUStats {
	return &CPUStats{
		ps:             ps,
		CollectCPUTime: true,
		ReportActive:   true,
	}
}

func (_ *CPUStats) Description() string {
	return "Read metrics about cpu usage"
}

var sampleConfig = `
  ## Whether to report per-cpu stats or not
  percpu = true
  ## Whether to report total system cpu stats or not
  totalcpu = true
  ## If true, collect raw CPU time metrics
  collect_cpu_time = false
  ## If true, compute and report the sum of all non-idle CPU states
  report_active = false
`

func (_ *CPUStats) SampleConfig() string {
	return sampleConfig
}

func (s *CPUStats) Gather(acc telegraf.Accumulator) error {
	times, err := s.ps.CPUTimes(s.PerCPU, s.TotalCPU)
	if err != nil {
		return fmt.Errorf("error getting CPU info: %s", err)
	}
	now := time.Now()

	for _, cts := range times {
		tags := map[string]string{
			"cpu": cts.CPU,
		}

		total := totalCpuTime(cts)
		active := activeCpuTime(cts)

		if s.CollectCPUTime {
			// Add cpu time metrics
			fieldsC := map[string]interface{}{
				"time_user":       cts.User,
				"time_system":     cts.System,
				"time_idle":       cts.Idle,
				"time_nice":       cts.Nice,
				"time_iowait":     cts.Iowait,
				"time_irq":        cts.Irq,
				"time_softirq":    cts.Softirq,
				"time_steal":      cts.Steal,
				"time_guest":      cts.Guest,
				"time_guest_nice": cts.GuestNice,
			}
			if s.ReportActive {
				fieldsC["time_active"] = activeCpuTime(cts)
			}
			acc.AddCounter("cpu", fieldsC, tags, now)
		}

		// Add in percentage
		if len(s.lastStats) == 0 {
			// If it's the 1st gather, can't get CPU Usage stats yet
			continue
		}

		lastCts, ok := s.lastStats[cts.CPU]
		if !ok {
			continue
		}
		lastTotal := totalCpuTime(lastCts)
		lastActive := activeCpuTime(lastCts)
		totalDelta := total - lastTotal

		if totalDelta < 0 {
			err = fmt.Errorf("Error: current total CPU time is less than previous total CPU time")
			break
		}

		if totalDelta == 0 {
			continue
		}

		fieldsG := map[string]interface{}{
			"usage_user":       100 * (cts.User - lastCts.User - (cts.Guest - lastCts.Guest)) / totalDelta,
			"usage_system":     100 * (cts.System - lastCts.System) / totalDelta,
			"usage_idle":       100 * (cts.Idle - lastCts.Idle) / totalDelta,
			"usage_nice":       100 * (cts.Nice - lastCts.Nice - (cts.GuestNice - lastCts.GuestNice)) / totalDelta,
			"usage_iowait":     100 * (cts.Iowait - lastCts.Iowait) / totalDelta,
			"usage_irq":        100 * (cts.Irq - lastCts.Irq) / totalDelta,
			"usage_softirq":    100 * (cts.Softirq - lastCts.Softirq) / totalDelta,
			"usage_steal":      100 * (cts.Steal - lastCts.Steal) / totalDelta,
			"usage_guest":      100 * (cts.Guest - lastCts.Guest) / totalDelta,
			"usage_guest_nice": 100 * (cts.GuestNice - lastCts.GuestNice) / totalDelta,
		}
		if s.ReportActive {
			fieldsG["usage_active"] = 100 * (active - lastActive) / totalDelta
		}
		acc.AddGauge("cpu", fieldsG, tags, now)
	}

	s.lastStats = make(map[string]cpu.TimesStat)
	for _, cts := range times {
		s.lastStats[cts.CPU] = cts
	}

	return err
}

func totalCpuTime(t cpu.TimesStat) float64 {
	total := t.User + t.System + t.Nice + t.Iowait + t.Irq + t.Softirq + t.Steal +
		t.Idle
	return total
}

func activeCpuTime(t cpu.TimesStat) float64 {
	active := totalCpuTime(t) - t.Idle
	return active
}

func init() {
	inputs.Add("cpu", func() telegraf.Input {
		return &CPUStats{
			PerCPU:   true,
			TotalCPU: true,
			ps:       system.NewSystemPS(),
		}
	})
}
<|endoftext|>


<commit_before>package main

// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var serviceTmpl = `
// Autogenerated by thrift-gen. Do not modify.
package {{ .Package }}

import (
"fmt"

athrift "github.com/apache/thrift/lib/go/thrift"
"github.com/uber/tchannel/golang/thrift"
)

// Interfaces for the service and client for the services defined in the IDL.

{{ range .Services }}
type {{ .Interface }} interface {
	{{ range .Methods }}
		{{ .Name }}({{ .ArgList }}) {{ .RetType }}
	{{ end }}
}
{{ end }}

// Implementation of a client and service handler.

{{/* Generate client and service implementations for the above interfaces. */}}
{{ range $svc := .Services }}
type {{ .ClientStruct }} struct {
	client thrift.TChanClient
}

func {{ .ClientConstructor }}(client thrift.TChanClient) {{ .Interface }} {
	return &{{ .ClientStruct }}{client: client}
}

{{ range .Methods }}
	func (c *{{ $svc.ClientStruct }}) {{ .Name }}({{ .ArgList }}) {{ .RetType }} {
		var resp {{ .ResultType }}
		args := {{ .ArgsType }}{
			{{ range .Arguments }}
				{{ .ArgStructName }}: {{ .Name }},
			{{ end }}
		}
		success, err := c.client.Call(ctx, "{{ $svc.ThriftName }}", "{{ .ThriftName }}", &args, &resp)
		if err == nil && !success {
			{{ range .Exceptions }}
				if e := resp.{{ .ArgStructName }}; e != nil {
					err = e
				}
			{{ end }}
		}

		{{ if .HasReturn }}
			return resp.GetSuccess(), err
		{{ else }}
			return err
		{{ end }}
	}
{{ end }}

type {{ .ServerStruct }} struct {
	handler {{ .Interface }}
}

func {{ .ServerConstructor }}(handler {{ .Interface }}) thrift.TChanServer {
	return &{{ .ServerStruct }}{handler}
}

func (s *{{ .ServerStruct }}) Service() string {
	return "{{ .ThriftName }}"
}

func (s *{{ .ServerStruct }}) Methods() []string {
	return []string{
		{{ range .Methods }}
			"{{ .ThriftName }}",
		{{ end }}
	}
}

func (s *{{ .ServerStruct }}) Handle(ctx {{ contextType }}, methodName string, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
	switch methodName {
		{{ range .Methods }}
			case "{{ .ThriftName }}":
				return s.{{ .HandleFunc }}(ctx, protocol)
		{{ end }}
		default:
			return false, nil, fmt.Errorf("method %v not found in service %v", methodName, s.Service())
	}
}

{{ range .Methods }}
	func (s *{{ $svc.ServerStruct }}) {{ .HandleFunc }}(ctx {{ contextType }}, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
		var req {{ .ArgsType }}
		var res {{ .ResultType }}

		if err := req.Read(protocol); err != nil {
			return false, nil, err
		}

		{{ if .HasReturn }}
			r, err :=
		{{ else }}
			err :=
		{{ end }}
				s.handler.{{ .Name }}({{ .CallList "req" }})

		if err != nil {
			{{ if .HasExceptions }}
			switch v := err.(type) {
				{{ range .Exceptions }}
					case {{ .ArgType }}:
						res.{{ .ArgStructName }} = v
				{{ end }}
					default:
						return false, nil, err
			}
			{{ else }}
				return false, nil, err
			{{ end }}
		}
		{{ if .HasReturn }}
		res.Success = {{ .WrapResult "r" }}
		{{ end }}

		return err == nil, &res, nil
	}

{{ end }}

{{ end }}
`
<commit_msg>Only set response if there is no error.<commit_after>package main

// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var serviceTmpl = `
// Autogenerated by thrift-gen. Do not modify.
package {{ .Package }}

import (
"fmt"

athrift "github.com/apache/thrift/lib/go/thrift"
"github.com/uber/tchannel/golang/thrift"
)

// Interfaces for the service and client for the services defined in the IDL.

{{ range .Services }}
type {{ .Interface }} interface {
	{{ range .Methods }}
		{{ .Name }}({{ .ArgList }}) {{ .RetType }}
	{{ end }}
}
{{ end }}

// Implementation of a client and service handler.

{{/* Generate client and service implementations for the above interfaces. */}}
{{ range $svc := .Services }}
type {{ .ClientStruct }} struct {
	client thrift.TChanClient
}

func {{ .ClientConstructor }}(client thrift.TChanClient) {{ .Interface }} {
	return &{{ .ClientStruct }}{client: client}
}

{{ range .Methods }}
	func (c *{{ $svc.ClientStruct }}) {{ .Name }}({{ .ArgList }}) {{ .RetType }} {
		var resp {{ .ResultType }}
		args := {{ .ArgsType }}{
			{{ range .Arguments }}
				{{ .ArgStructName }}: {{ .Name }},
			{{ end }}
		}
		success, err := c.client.Call(ctx, "{{ $svc.ThriftName }}", "{{ .ThriftName }}", &args, &resp)
		if err == nil && !success {
			{{ range .Exceptions }}
				if e := resp.{{ .ArgStructName }}; e != nil {
					err = e
				}
			{{ end }}
		}

		{{ if .HasReturn }}
			return resp.GetSuccess(), err
		{{ else }}
			return err
		{{ end }}
	}
{{ end }}

type {{ .ServerStruct }} struct {
	handler {{ .Interface }}
}

func {{ .ServerConstructor }}(handler {{ .Interface }}) thrift.TChanServer {
	return &{{ .ServerStruct }}{handler}
}

func (s *{{ .ServerStruct }}) Service() string {
	return "{{ .ThriftName }}"
}

func (s *{{ .ServerStruct }}) Methods() []string {
	return []string{
		{{ range .Methods }}
			"{{ .ThriftName }}",
		{{ end }}
	}
}

func (s *{{ .ServerStruct }}) Handle(ctx {{ contextType }}, methodName string, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
	switch methodName {
		{{ range .Methods }}
			case "{{ .ThriftName }}":
				return s.{{ .HandleFunc }}(ctx, protocol)
		{{ end }}
		default:
			return false, nil, fmt.Errorf("method %v not found in service %v", methodName, s.Service())
	}
}

{{ range .Methods }}
	func (s *{{ $svc.ServerStruct }}) {{ .HandleFunc }}(ctx {{ contextType }}, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
		var req {{ .ArgsType }}
		var res {{ .ResultType }}

		if err := req.Read(protocol); err != nil {
			return false, nil, err
		}

		{{ if .HasReturn }}
			r, err :=
		{{ else }}
			err :=
		{{ end }}
				s.handler.{{ .Name }}({{ .CallList "req" }})

		if err != nil {
			{{ if .HasExceptions }}
			switch v := err.(type) {
				{{ range .Exceptions }}
					case {{ .ArgType }}:
						res.{{ .ArgStructName }} = v
				{{ end }}
					default:
						return false, nil, err
			}
			{{ else }}
				return false, nil, err
			{{ end }}
		} else {
    {{ if .HasReturn }}
		  res.Success = {{ .WrapResult "r" }}
		{{ end }}
    }

		return err == nil, &res, nil
	}

{{ end }}

{{ end }}
`
<|endoftext|>


<commit_before>package smd

import (
	"fmt"
	"testing"
	"time"

	"github.com/gonum/floats"
	"github.com/gonum/matrix/mat64"
)

func TestEstimate(t *testing.T) {
	// Test that an estimate does propagate the same way as "Mission".
	perts := Perturbations{Jn: 3}
	startDT := time.Now().UTC()
	duration := time.Duration(24) * time.Hour
	endDT := startDT.Add(duration)
	// Define the orbits
	leoMission := NewOrbitFromOE(7000, 0.00001, 30, 80, 40, 0, Earth)
	leoEstimate := *NewOrbitFromOE(7000, 0.00001, 30, 80, 40, 0, Earth)
	// Initialize the mission and estimates
	mission := NewPreciseMission(NewEmptySC("LEO", 0), leoMission, startDT, endDT, Cartesian, perts, time.Second, ExportConfig{})
	orbitEstimate := NewOrbitEstimate("estimator", leoEstimate, perts, startDT, time.Second)
	// Run
	mission.Propagate()
	orbitEstimate.PropagateUntil(endDT)
	finalEst := orbitEstimate.State()
	finalR, finalV := finalEst.Orbit.RV()
	missionR, missionV := leoMission.RV()
	if !finalEst.DT.UTC().Equal(mission.CurrentDT.UTC()) {
		t.Logf("\nEst.:%s\nMis.:%s", finalEst.DT.UTC(), mission.CurrentDT.UTC())
		t.Fatal("incorrect ending date")
	}
	if !vectorsEqual(finalR, missionR) || !vectorsEqual(finalV, missionV) {
		t.Logf("\nEst.: R=%+v\tV=%+v\nMis.: R=%+v\tV=%+v\t(truth)", finalR, finalV, missionR, missionV)
		t.Fatal("incorrect final vectors")
	}
	// Test Φ
	var inv, id mat64.Dense
	if ierr := inv.Inverse(orbitEstimate.Φ); ierr != nil {
		t.Fatalf("could not inverse Φ: %s ", ierr)
	}
	id.Mul(orbitEstimate.Φ, &inv)
	t.Logf("\n%+v", mat64.Formatted(&id))
}

func TestEstimate1DayNoJ2(t *testing.T) {
	virtObj := CelestialObject{"virtObj", 6378.145, 149598023, 398600.4, 23.4, 0.00005, 924645.0, 0.00108248, -2.5324e-6, -1.6204e-6, nil}
	orbit := NewOrbitFromRV([]float64{-2436.45, -2436.45, 6891.037}, []float64{5.088611, -5.088611, 0}, virtObj)
	startDT := time.Now()
	endDT := startDT.Add(24 * time.Hour)
	orbitEstimate := NewOrbitEstimate("estimator", *orbit, Perturbations{}, startDT, time.Second)
	orbitEstimate.PropagateUntil(endDT)
	rVec, vVec := orbitEstimate.State().Orbit.RV()
	expR := []float64{-5971.19544867343, 3945.58315019255, 2864.53021742433}
	expV := []float64{0.049002818030, -4.185030861883, 5.848985672439}
	if !floats.EqualApprox(rVec, expR, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", rVec, expR)
	}
	if !floats.EqualApprox(vVec, expV, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", vVec, expV)
	}
}

func TestEstimate1DayWithJ2(t *testing.T) {
	virtObj := CelestialObject{"virtObj", 6378.145, 149598023, 398600.4, 23.4, 0.00005, 924645.0, 0.00108248, -2.5324e-6, -1.6204e-6, nil}
	orbit := NewOrbitFromRV([]float64{-2436.45, -2436.45, 6891.037}, []float64{5.088611, -5.088611, 0}, virtObj)
	startDT := time.Now()
	endDT := startDT.Add(24 * time.Hour)
	orbitEstimate := NewOrbitEstimate("estimator", *orbit, Perturbations{Jn: 2}, startDT, time.Second)
	orbitEstimate.PropagateUntil(endDT)
	expR := []float64{-5751.49900721589, 4721.14371040552, 2046.03583664311}
	expV := []float64{-0.797658631074, -3.656513108387, 6.139612016678}
	rVec, vVec := orbitEstimate.State().Orbit.RV()
	if !floats.EqualApprox(rVec, expR, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", rVec, expR)
	}
	if !floats.EqualApprox(vVec, expV, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", vVec, expV)
	}
}

func TestEstimatePhi(t *testing.T) {
	perts := Perturbations{Jn: 3}
	startDT := time.Now().UTC()
	duration0 := time.Duration(30) * time.Second
	duration2 := time.Duration(15) * time.Second
	endDT := startDT.Add(duration0)
	endDT1 := startDT.Add(duration2)
	leoEstimate := *NewOrbitFromOE(7000, 0.00001, 30, 80, 40, 0, Earth)
	est0 := NewOrbitEstimate("full", leoEstimate, perts, startDT, time.Second)
	est0.PropagateUntil(endDT)
	est1 := NewOrbitEstimate("part1", leoEstimate, perts, startDT, time.Second)
	est1.PropagateUntil(endDT1)
	// Start the second estimate from the end of the first one.
	state := est1.State()
	est2 := NewOrbitEstimate("part2", state.Orbit, perts, startDT.Add(duration2), time.Second)
	est2.PropagateUntil(endDT)
	var est1ΦInv mat64.Dense
	if ierr := est1ΦInv.Inverse(est1.Φ); ierr != nil {
		panic(fmt.Errorf("could not invert `est1.Φ`: %s", ierr))
	}
	var Φ2 mat64.Dense
	Φ2.Mul(est0.Φ, &est1ΦInv)
	if !mat64.EqualApprox(&Φ2, est2.Φ, 1e-12) {
		t.Logf("\n%+v", mat64.Formatted(&Φ2))
		t.Fatal("did not get Φ2 correctly")
	}

}
<commit_msg>The Phi test is totally wrong. I gotta check what Phi I'm actually showing.<commit_after>package smd

import (
	"fmt"
	"testing"
	"time"

	"github.com/gonum/floats"
	"github.com/gonum/matrix/mat64"
)

func TestEstimate(t *testing.T) {
	// Test that an estimate does propagate the same way as "Mission".
	perts := Perturbations{Jn: 3}
	startDT := time.Now().UTC()
	duration := time.Duration(24) * time.Hour
	endDT := startDT.Add(duration)
	// Define the orbits
	leoMission := NewOrbitFromOE(7000, 0.00001, 30, 80, 40, 0, Earth)
	leoEstimate := *NewOrbitFromOE(7000, 0.00001, 30, 80, 40, 0, Earth)
	// Initialize the mission and estimates
	mission := NewPreciseMission(NewEmptySC("LEO", 0), leoMission, startDT, endDT, Cartesian, perts, time.Second, ExportConfig{})
	orbitEstimate := NewOrbitEstimate("estimator", leoEstimate, perts, startDT, time.Second)
	// Run
	mission.Propagate()
	orbitEstimate.PropagateUntil(endDT)
	finalEst := orbitEstimate.State()
	finalR, finalV := finalEst.Orbit.RV()
	missionR, missionV := leoMission.RV()
	if !finalEst.DT.UTC().Equal(mission.CurrentDT.UTC()) {
		t.Logf("\nEst.:%s\nMis.:%s", finalEst.DT.UTC(), mission.CurrentDT.UTC())
		t.Fatal("incorrect ending date")
	}
	if !vectorsEqual(finalR, missionR) || !vectorsEqual(finalV, missionV) {
		t.Logf("\nEst.: R=%+v\tV=%+v\nMis.: R=%+v\tV=%+v\t(truth)", finalR, finalV, missionR, missionV)
		t.Fatal("incorrect final vectors")
	}
	// Test Φ
	var inv, id mat64.Dense
	if ierr := inv.Inverse(orbitEstimate.Φ); ierr != nil {
		t.Fatalf("could not inverse Φ: %s ", ierr)
	}
	id.Mul(orbitEstimate.Φ, &inv)
	t.Logf("\n%+v", mat64.Formatted(&id))
}

func TestEstimate1DayNoJ2(t *testing.T) {
	virtObj := CelestialObject{"virtObj", 6378.145, 149598023, 398600.4, 23.4, 0.00005, 924645.0, 0.00108248, -2.5324e-6, -1.6204e-6, nil}
	orbit := NewOrbitFromRV([]float64{-2436.45, -2436.45, 6891.037}, []float64{5.088611, -5.088611, 0}, virtObj)
	startDT := time.Now()
	endDT := startDT.Add(24 * time.Hour)
	orbitEstimate := NewOrbitEstimate("estimator", *orbit, Perturbations{}, startDT, time.Second)
	orbitEstimate.PropagateUntil(endDT)
	rVec, vVec := orbitEstimate.State().Orbit.RV()
	expR := []float64{-5971.19544867343, 3945.58315019255, 2864.53021742433}
	expV := []float64{0.049002818030, -4.185030861883, 5.848985672439}
	if !floats.EqualApprox(rVec, expR, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", rVec, expR)
	}
	if !floats.EqualApprox(vVec, expV, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", vVec, expV)
	}
}

func TestEstimate1DayWithJ2(t *testing.T) {
	virtObj := CelestialObject{"virtObj", 6378.145, 149598023, 398600.4, 23.4, 0.00005, 924645.0, 0.00108248, -2.5324e-6, -1.6204e-6, nil}
	orbit := NewOrbitFromRV([]float64{-2436.45, -2436.45, 6891.037}, []float64{5.088611, -5.088611, 0}, virtObj)
	startDT := time.Now()
	endDT := startDT.Add(24 * time.Hour)
	orbitEstimate := NewOrbitEstimate("estimator", *orbit, Perturbations{Jn: 2}, startDT, time.Second)
	orbitEstimate.PropagateUntil(endDT)
	expR := []float64{-5751.49900721589, 4721.14371040552, 2046.03583664311}
	expV := []float64{-0.797658631074, -3.656513108387, 6.139612016678}
	rVec, vVec := orbitEstimate.State().Orbit.RV()
	if !floats.EqualApprox(rVec, expR, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", rVec, expR)
	}
	if !floats.EqualApprox(vVec, expV, 1e-8) {
		t.Fatalf("Incorrect R:\ngot: %+v\nexp: %+v", vVec, expV)
	}
}

func TestEstimateArbitraryPhi(t *testing.T) {
	perts := Perturbations{Jn: 3}
	startDT := time.Now().UTC()
	duration0 := time.Duration(30) * time.Second
	duration2 := time.Duration(15) * time.Second
	endDT := startDT.Add(duration0)
	endDT1 := startDT.Add(duration2)
	leoEstimate := *NewOrbitFromOE(7000, 0.00001, 30, 80, 40, 0, Earth)
	est0 := NewOrbitEstimate("full", leoEstimate, perts, startDT, time.Second)
	est0.PropagateUntil(endDT)
	est1 := NewOrbitEstimate("part1", leoEstimate, perts, startDT, time.Second)
	est1.PropagateUntil(endDT1)
	// Start the second estimate from the end of the first one.
	state := est1.State()
	est2 := NewOrbitEstimate("part2", state.Orbit, perts, startDT.Add(duration2), time.Second)
	est2.PropagateUntil(endDT)
	var est1ΦInv mat64.Dense
	if ierr := est1ΦInv.Inverse(est1.Φ); ierr != nil {
		panic(fmt.Errorf("could not invert `est1.Φ`: %s", ierr))
	}
	var Φ2 mat64.Dense
	Φ2.Mul(est0.Φ, &est1ΦInv)
	if !mat64.EqualApprox(&Φ2, est2.Φ, 1e-12) {
		t.Logf("\n%+v", mat64.Formatted(&Φ2))
		t.Fatal("did not get Φ2 correctly")
	}

}

func TestEstimatePhi(t *testing.T) {
	virtObj := CelestialObject{"normalized", 6378.145, 149598023, 1, 23.4, 0.00005, 924645.0, 0.00108248, -2.5324e-6, -1.6204e-6, nil}
	orbit := NewOrbitFromRV([]float64{1, 0, 0}, []float64{0, 1, 0}, virtObj)
	startDT := time.Now()
	orbitEstimate := NewOrbitEstimate("estimator", *orbit, Perturbations{}, startDT, time.Second)
	t.Logf("t0\n%v", mat64.Formatted(orbitEstimate.Φ))
	orbitEstimate.PropagateUntil(orbitEstimate.dt.Add(10 * time.Second))
	t.Logf("t10\n%v", mat64.Formatted(orbitEstimate.Φ))
	orbitEstimate.PropagateUntil(orbitEstimate.dt.Add(100 * time.Second))
	t.Logf("t100\n%v", mat64.Formatted(orbitEstimate.Φ))
}
<|endoftext|>


<commit_before>// Copyright 2015 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package etcdmain

import (
	"fmt"
	"os"
	"strings"

	"github.com/coreos/go-systemd/v22/daemon"
	"go.uber.org/zap"
)

func Main() {
	checkSupportArch()

	if len(os.Args) > 1 {
		cmd := os.Args[1]
		if covArgs := os.Getenv("ETCDCOV_ARGS"); len(covArgs) > 0 {
			args := strings.Split(os.Getenv("ETCDCOV_ARGS"), "\xe7\xcd")[1:]
			rootCmd.SetArgs(args)
			cmd = "grpc-proxy"
		}
		switch cmd {
		case "gateway", "grpc-proxy":
			if err := rootCmd.Execute(); err != nil {
				fmt.Fprint(os.Stderr, err)
				os.Exit(1)
			}
			return
		}
	}

	startEtcdOrProxyV2()
}

func notifySystemd(lg *zap.Logger) {
	_, err := daemon.SdNotify(false, daemon.SdNotifyReady)
	if err != nil {
		if lg != nil {
			lg.Error("failed to notify systemd for readiness", zap.Error(err))
		}
	}
}
<commit_msg>etcdmain: log "SdNotify" error/success<commit_after>// Copyright 2015 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package etcdmain

import (
	"fmt"
	"os"
	"strings"

	"github.com/coreos/go-systemd/v22/daemon"
	"go.uber.org/zap"
)

func Main() {
	checkSupportArch()

	if len(os.Args) > 1 {
		cmd := os.Args[1]
		if covArgs := os.Getenv("ETCDCOV_ARGS"); len(covArgs) > 0 {
			args := strings.Split(os.Getenv("ETCDCOV_ARGS"), "\xe7\xcd")[1:]
			rootCmd.SetArgs(args)
			cmd = "grpc-proxy"
		}
		switch cmd {
		case "gateway", "grpc-proxy":
			if err := rootCmd.Execute(); err != nil {
				fmt.Fprint(os.Stderr, err)
				os.Exit(1)
			}
			return
		}
	}

	startEtcdOrProxyV2()
}

func notifySystemd(lg *zap.Logger) {
	if lg == nil {
		lg = zap.NewExample()
	}
	lg.Info("notifying init daemon")
	_, err := daemon.SdNotify(false, daemon.SdNotifyReady)
	if err != nil {
		lg.Error("failed to notify systemd for readiness", zap.Error(err))
		return
	}
	lg.Info("successfully notified init daemon")
}
<|endoftext|>


<commit_before>// Copyright 2014 The Cayley Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bolt

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/barakmich/glog"
	"github.com/boltdb/bolt"

	"github.com/google/cayley/graph"
	"github.com/google/cayley/graph/iterator"
	"github.com/google/cayley/quad"
)

type AllIterator struct {
	uid    uint64
	tags   graph.Tagger
	bucket []byte
	dir    quad.Direction
	qs     *QuadStore
	result *Token
	buffer [][]byte
	offset int
	done   bool
}

func NewAllIterator(bucket []byte, d quad.Direction, qs *QuadStore) *AllIterator {

	it := AllIterator{
		uid:    iterator.NextUID(),
		bucket: bucket,
		dir:    d,
		qs:     qs,
	}

	return &it
}

func (it *AllIterator) UID() uint64 {
	return it.uid
}

func (it *AllIterator) Reset() {
	it.buffer = nil
	it.offset = 0
	it.done = false
}

func (it *AllIterator) Tagger() *graph.Tagger {
	return &it.tags
}

func (it *AllIterator) TagResults(dst map[string]graph.Value) {
	for _, tag := range it.tags.Tags() {
		dst[tag] = it.Result()
	}

	for tag, value := range it.tags.Fixed() {
		dst[tag] = value
	}
}

func (it *AllIterator) Clone() graph.Iterator {
	out := NewAllIterator(it.bucket, it.dir, it.qs)
	out.tags.CopyFrom(it)
	return out
}

func (it *AllIterator) Next() bool {
	if it.done {
		return false
	}
	if len(it.buffer) <= it.offset+1 {
		it.offset = 0
		var last []byte
		if it.buffer != nil {
			last = it.buffer[len(it.buffer)-1]
		}
		it.buffer = make([][]byte, 0, bufferSize)
		err := it.qs.db.View(func(tx *bolt.Tx) error {
			i := 0
			b := tx.Bucket(it.bucket)
			cur := b.Cursor()
			if last == nil {
				k, _ := cur.First()
				var out []byte
				out = make([]byte, len(k))
				copy(out, k)
				it.buffer = append(it.buffer, out)
				i++
			} else {
				k, _ := cur.Seek(last)
				if !bytes.Equal(k, last) {
					return fmt.Errorf("Couldn't pick up after", k)
				}
			}
			for i < bufferSize {
				k, _ := cur.Next()
				if k == nil {
					it.buffer = append(it.buffer, k)
					break
				}
				var out []byte
				out = make([]byte, len(k))
				copy(out, k)
				it.buffer = append(it.buffer, out)
				i++
			}
			return nil
		})
		if err != nil {
			glog.Error("Error nexting in database: ", err)
			it.done = true
			return false
		}
	} else {
		it.offset++
	}
	if it.Result() == nil {
		it.done = true
		return false
	}
	return true
}

func (it *AllIterator) ResultTree() *graph.ResultTree {
	return graph.NewResultTree(it.Result())
}

func (it *AllIterator) Result() graph.Value {
	if it.done {
		return nil
	}
	if it.result != nil {
		return it.result
	}
	if it.offset >= len(it.buffer) {
		return nil
	}
	return &Token{bucket: it.bucket, key: it.buffer[it.offset]}
}

func (it *AllIterator) NextPath() bool {
	return false
}

// No subiterators.
func (it *AllIterator) SubIterators() []graph.Iterator {
	return nil
}

func (it *AllIterator) Contains(v graph.Value) bool {
	it.result = v.(*Token)
	return true
}

func (it *AllIterator) Close() {
	it.result = nil
	it.buffer = nil
	it.done = true
}

func (it *AllIterator) Size() (int64, bool) {
	return it.qs.size, true
}

func (it *AllIterator) DebugString(indent int) string {
	size, _ := it.Size()
	return fmt.Sprintf("%s(%s tags: %v bolt size:%d %s %p)", strings.Repeat(" ", indent), it.Type(), it.tags.Tags(), size, it.dir, it)
}

func (it *AllIterator) Type() graph.Type { return graph.All }
func (it *AllIterator) Sorted() bool     { return false }

func (it *AllIterator) Optimize() (graph.Iterator, bool) {
	return it, false
}

func (it *AllIterator) Stats() graph.IteratorStats {
	s, _ := it.Size()
	return graph.IteratorStats{
		ContainsCost: 1,
		NextCost:     2,
		Size:         s,
	}
}
<commit_msg>fix all iterator<commit_after>// Copyright 2014 The Cayley Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bolt

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/barakmich/glog"
	"github.com/boltdb/bolt"

	"github.com/google/cayley/graph"
	"github.com/google/cayley/graph/iterator"
	"github.com/google/cayley/quad"
)

type AllIterator struct {
	uid    uint64
	tags   graph.Tagger
	bucket []byte
	dir    quad.Direction
	qs     *QuadStore
	result *Token
	buffer [][]byte
	offset int
	done   bool
}

func NewAllIterator(bucket []byte, d quad.Direction, qs *QuadStore) *AllIterator {

	it := AllIterator{
		uid:    iterator.NextUID(),
		bucket: bucket,
		dir:    d,
		qs:     qs,
	}

	return &it
}

func (it *AllIterator) UID() uint64 {
	return it.uid
}

func (it *AllIterator) Reset() {
	it.buffer = nil
	it.offset = 0
	it.done = false
}

func (it *AllIterator) Tagger() *graph.Tagger {
	return &it.tags
}

func (it *AllIterator) TagResults(dst map[string]graph.Value) {
	for _, tag := range it.tags.Tags() {
		dst[tag] = it.Result()
	}

	for tag, value := range it.tags.Fixed() {
		dst[tag] = value
	}
}

func (it *AllIterator) Clone() graph.Iterator {
	out := NewAllIterator(it.bucket, it.dir, it.qs)
	out.tags.CopyFrom(it)
	return out
}

func (it *AllIterator) Next() bool {
	if it.done {
		return false
	}
	if len(it.buffer) <= it.offset+1 {
		it.offset = 0
		var last []byte
		if it.buffer != nil {
			last = it.buffer[len(it.buffer)-1]
		}
		it.buffer = make([][]byte, 0, bufferSize)
		err := it.qs.db.View(func(tx *bolt.Tx) error {
			i := 0
			b := tx.Bucket(it.bucket)
			cur := b.Cursor()
			if last == nil {
				k, _ := cur.First()
				var out []byte
				out = make([]byte, len(k))
				copy(out, k)
				it.buffer = append(it.buffer, out)
				i++
			} else {
				k, _ := cur.Seek(last)
				if !bytes.Equal(k, last) {
					return fmt.Errorf("Couldn't pick up after", k)
				}
			}
			for i < bufferSize {
				k, _ := cur.Next()
				if k == nil {
					it.buffer = append(it.buffer, k)
					break
				}
				var out []byte
				out = make([]byte, len(k))
				copy(out, k)
				it.buffer = append(it.buffer, out)
				i++
			}
			return nil
		})
		if err != nil {
			glog.Error("Error nexting in database: ", err)
			it.done = true
			return false
		}
	} else {
		it.offset++
	}
	if it.Result() == nil {
		it.done = true
		return false
	}
	return true
}

func (it *AllIterator) ResultTree() *graph.ResultTree {
	return graph.NewResultTree(it.Result())
}

func (it *AllIterator) Result() graph.Value {
	if it.done {
		return nil
	}
	if it.result != nil {
		return it.result
	}
	if it.offset >= len(it.buffer) {
		return nil
	}
	if it.buffer[it.offset] == nil {
		return nil
	}
	return &Token{bucket: it.bucket, key: it.buffer[it.offset]}
}

func (it *AllIterator) NextPath() bool {
	return false
}

// No subiterators.
func (it *AllIterator) SubIterators() []graph.Iterator {
	return nil
}

func (it *AllIterator) Contains(v graph.Value) bool {
	it.result = v.(*Token)
	return true
}

func (it *AllIterator) Close() {
	it.result = nil
	it.buffer = nil
	it.done = true
}

func (it *AllIterator) Size() (int64, bool) {
	return it.qs.size, true
}

func (it *AllIterator) DebugString(indent int) string {
	size, _ := it.Size()
	return fmt.Sprintf("%s(%s tags: %v bolt size:%d %s %p)", strings.Repeat(" ", indent), it.Type(), it.tags.Tags(), size, it.dir, it)
}

func (it *AllIterator) Type() graph.Type { return graph.All }
func (it *AllIterator) Sorted() bool     { return false }

func (it *AllIterator) Optimize() (graph.Iterator, bool) {
	return it, false
}

func (it *AllIterator) Stats() graph.IteratorStats {
	s, _ := it.Size()
	return graph.IteratorStats{
		ContainsCost: 1,
		NextCost:     2,
		Size:         s,
	}
}
<|endoftext|>


<commit_before>package event

import (
	"fmt"
	"net/http"
	"strconv"

	"github.com/concourse/atc/builds"
	"github.com/concourse/atc/db"
	troutes "github.com/concourse/turbine/routes"
	"github.com/tedsuo/rata"
	"github.com/vito/go-sse/sse"
)

type BuildsDB interface {
	GetBuild(buildID int) (builds.Build, error)
	BuildEvents(buildID int) ([]db.BuildEvent, error)
}

type Censor func(sse.Event) (sse.Event, error)

func NewHandler(db BuildsDB, buildID int, censor Censor) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		build, err := db.GetBuild(buildID)
		if err != nil {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		flusher := w.(http.Flusher)

		w.Header().Add("Content-Type", "text/event-stream; charset=utf-8")
		w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
		w.Header().Add("Connection", "keep-alive")

		if build.Status == builds.StatusStarted {
			generator := rata.NewRequestGenerator(build.Endpoint, troutes.Routes)

			events, err := generator.CreateRequest(
				troutes.GetBuildEvents,
				rata.Params{"guid": build.Guid},
				nil,
			)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				return
			}

			events.Header.Set("Last-Event-ID", r.Header.Get("Last-Event-ID"))

			resp, err := http.DefaultClient.Do(events)
			if err != nil {
				w.WriteHeader(http.StatusServiceUnavailable)
				return
			}

			w.WriteHeader(http.StatusOK)

			flusher.Flush()

			reader := sse.NewReader(resp.Body)

			for {
				ev, err := reader.Next()
				if err != nil {
					return
				}

				if censor != nil {
					ev, err = censor(ev)
					if err != nil {
						return
					}
				}

				err = ev.Write(w)
				if err != nil {
					return
				}

				flusher.Flush()
			}
		} else {
			events, err := db.BuildEvents(buildID)
			if err != nil {
				w.WriteHeader(http.StatusServiceUnavailable)
				return
			}

			start := 0
			if r.Header.Get("Last-Event-ID") != "" {
				var err error

				lastEvent, err := strconv.Atoi(r.Header.Get("Last-Event-ID"))
				if err != nil {
					w.WriteHeader(http.StatusBadRequest)
					return
				}

				start = lastEvent + 1
			}

			if start >= len(events) {
				return
			}

			for idx, event := range events[start:] {
				ev := sse.Event{
					ID:   fmt.Sprintf("%d", idx+start),
					Name: event.Type,
					Data: []byte(event.Payload),
				}

				if censor != nil {
					ev, err = censor(ev)
					if err != nil {
						return
					}
				}

				err := ev.Write(w)
				if err != nil {
					return
				}

				flusher.Flush()
			}
		}

		return
	})
}
<commit_msg>don't leak event response body<commit_after>package event

import (
	"fmt"
	"net/http"
	"strconv"

	"github.com/concourse/atc/builds"
	"github.com/concourse/atc/db"
	troutes "github.com/concourse/turbine/routes"
	"github.com/tedsuo/rata"
	"github.com/vito/go-sse/sse"
)

type BuildsDB interface {
	GetBuild(buildID int) (builds.Build, error)
	BuildEvents(buildID int) ([]db.BuildEvent, error)
}

type Censor func(sse.Event) (sse.Event, error)

func NewHandler(db BuildsDB, buildID int, censor Censor) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		build, err := db.GetBuild(buildID)
		if err != nil {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		flusher := w.(http.Flusher)

		w.Header().Add("Content-Type", "text/event-stream; charset=utf-8")
		w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
		w.Header().Add("Connection", "keep-alive")

		if build.Status == builds.StatusStarted {
			generator := rata.NewRequestGenerator(build.Endpoint, troutes.Routes)

			events, err := generator.CreateRequest(
				troutes.GetBuildEvents,
				rata.Params{"guid": build.Guid},
				nil,
			)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				return
			}

			events.Header.Set("Last-Event-ID", r.Header.Get("Last-Event-ID"))

			resp, err := http.DefaultClient.Do(events)
			if err != nil {
				w.WriteHeader(http.StatusServiceUnavailable)
				return
			}

			defer resp.Body.Close()

			w.WriteHeader(http.StatusOK)

			flusher.Flush()

			reader := sse.NewReader(resp.Body)

			for {
				ev, err := reader.Next()
				if err != nil {
					return
				}

				if censor != nil {
					ev, err = censor(ev)
					if err != nil {
						return
					}
				}

				err = ev.Write(w)
				if err != nil {
					return
				}

				flusher.Flush()
			}
		} else {
			events, err := db.BuildEvents(buildID)
			if err != nil {
				w.WriteHeader(http.StatusServiceUnavailable)
				return
			}

			start := 0
			if r.Header.Get("Last-Event-ID") != "" {
				var err error

				lastEvent, err := strconv.Atoi(r.Header.Get("Last-Event-ID"))
				if err != nil {
					w.WriteHeader(http.StatusBadRequest)
					return
				}

				start = lastEvent + 1
			}

			if start >= len(events) {
				return
			}

			for idx, event := range events[start:] {
				ev := sse.Event{
					ID:   fmt.Sprintf("%d", idx+start),
					Name: event.Type,
					Data: []byte(event.Payload),
				}

				if censor != nil {
					ev, err = censor(ev)
					if err != nil {
						return
					}
				}

				err := ev.Write(w)
				if err != nil {
					return
				}

				flusher.Flush()
			}
		}

		return
	})
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Huawei Technologies Co., Ltd. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
This module implements a entry into the OpenSDS northbound service.

*/

package controllers

import (
	"encoding/json"
	"fmt"
	log "github.com/golang/glog"
	"github.com/opensds/opensds/pkg/api/policy"
	c "github.com/opensds/opensds/pkg/context"
	"github.com/opensds/opensds/pkg/controller/client"
	"github.com/opensds/opensds/pkg/model"
	pb "github.com/opensds/opensds/pkg/model/proto"
	. "github.com/opensds/opensds/pkg/utils/config"
	"golang.org/x/net/context"
)

func NewMetricsPortal() *MetricsPortal {
	return &MetricsPortal{
		CtrClient: client.NewClient(),
	}
}

type MetricsPortal struct {
	BasePortal

	CtrClient client.Client
}

func (m *MetricsPortal) GetMetrics() {
	if !policy.Authorize(m.Ctx, "metrics:get") {
		return
	}
	ctx := c.GetContext(m.Ctx)
	var getMetricSpec = model.GetMetricSpec{
		BaseModel: &model.BaseModel{},
	}

	// Unmarshal the request body
	if err := json.NewDecoder(m.Ctx.Request.Body).Decode(&getMetricSpec); err != nil {
		errMsg := fmt.Sprintf("parse get metric request body failed: %s", err.Error())
		m.ErrorHandle(model.ErrorBadRequest, errMsg)
		return
	}

	m.SuccessHandle(StatusOK, nil)

	// NOTE:The real volume creation process.
	// Volume creation request is sent to the Dock. Dock will update volume status to "available"
	// after volume creation is completed.
	if err := m.CtrClient.Connect(CONF.OsdsLet.ApiEndpoint); err != nil {
		log.Error("when connecting controller client:", err)
		return
	}
	defer m.CtrClient.Close()

	opt := &pb.GetMetricsOpts{
		InstanceId: getMetricSpec.InstanceId,
		MetricName: getMetricSpec.MetricName,
		StartTime:  getMetricSpec.StartTime,
		EndTime:    getMetricSpec.EndTime,
		Context:    ctx.ToJson(),
	}
	res, err := m.CtrClient.GetMetrics(context.Background(), opt)

	if err != nil {
		log.Error("collect metrics failed in controller service:", err)
		return
	}

	m.SuccessHandle(StatusOK, []byte(res.GetResult().GetMessage()))

	return
}
<commit_msg>fixed review comments<commit_after>// Copyright (c) 2019 Huawei Technologies Co., Ltd. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
This module implements a entry into the OpenSDS northbound service.

*/

package controllers

import (
	"encoding/json"
	"fmt"
	log "github.com/golang/glog"
	"github.com/opensds/opensds/pkg/api/policy"
	c "github.com/opensds/opensds/pkg/context"
	"github.com/opensds/opensds/pkg/controller/client"
	"github.com/opensds/opensds/pkg/model"
	pb "github.com/opensds/opensds/pkg/model/proto"
	. "github.com/opensds/opensds/pkg/utils/config"
	"golang.org/x/net/context"
)

func NewMetricsPortal() *MetricsPortal {
	return &MetricsPortal{
		CtrClient: client.NewClient(),
	}
}

type MetricsPortal struct {
	BasePortal

	CtrClient client.Client
}

func (m *MetricsPortal) GetMetrics() {
	if !policy.Authorize(m.Ctx, "metrics:get") {
		return
	}
	ctx := c.GetContext(m.Ctx)
	var getMetricSpec = model.GetMetricSpec{
		BaseModel: &model.BaseModel{},
	}

	// Unmarshal the request body
	if err := json.NewDecoder(m.Ctx.Request.Body).Decode(&getMetricSpec); err != nil {
		errMsg := fmt.Sprintf("parse get metric request body failed: %s", err.Error())
		m.ErrorHandle(model.ErrorBadRequest, errMsg)
		return
	}

	if err := m.CtrClient.Connect(CONF.OsdsLet.ApiEndpoint); err != nil {
		log.Error("when connecting controller client:", err)
		return
	}
	defer m.CtrClient.Close()

	opt := &pb.GetMetricsOpts{
		InstanceId: getMetricSpec.InstanceId,
		MetricName: getMetricSpec.MetricName,
		StartTime:  getMetricSpec.StartTime,
		EndTime:    getMetricSpec.EndTime,
		Context:    ctx.ToJson(),
	}
	res, err := m.CtrClient.GetMetrics(context.Background(), opt)

	if err != nil {
		log.Error("collect metrics failed in controller service:", err)
		return
	}

	m.SuccessHandle(StatusOK, []byte(res.GetResult().GetMessage()))

	return
}
<|endoftext|>


<commit_before><commit_msg>fix handling sslcertificates<commit_after><|endoftext|>


<commit_before>package rest

import (
	"github.com/geodan/gost/src/sensorthings/models"
	"github.com/stretchr/testify/assert"
	"strings"
	"testing"
)

func TestCreateEndPoints(t *testing.T) {
	//arrange
	endpoints := CreateEndPoints("http://test.com")

	//assert
	assert.Equal(t, 10, len(endpoints))
}

func TestCreateEndPointVersion(t *testing.T) {
	//arrange
	ve := createVersion("http://test.com")

	//assert
	containsVersionPath := containsEndpoint("Version", ve.Operations)
	assert.Equal(t, true, containsVersionPath, "Version endpoint needs to contain an endpoint containing the path Version")
}

func containsEndpoint(epName string, eps []models.EndpointOperation) bool {
	for _, o := range eps {
		if strings.Contains(o.Path, "Version") {
			return true
		}
	}

	return false
}
<commit_msg>fix test<commit_after>package rest

import (
	"strings"
	"testing"

	"github.com/geodan/gost/src/sensorthings/models"
	"github.com/stretchr/testify/assert"
)

func TestCreateEndPoints(t *testing.T) {
	//arrange
	endpoints := CreateEndPoints("http://test.com")

	//assert
	assert.Equal(t, 10, len(endpoints))
}

func TestCreateEndPointVersion(t *testing.T) {
	//arrange
	ve := createVersionEndpoint("http://test.com")

	//assert
	containsVersionPath := containsEndpoint("Version", ve.Operations)
	assert.Equal(t, true, containsVersionPath, "Version endpoint needs to contain an endpoint containing the path Version")
}

func containsEndpoint(epName string, eps []models.EndpointOperation) bool {
	for _, o := range eps {
		if strings.Contains(o.Path, "Version") {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>// Package gff3 implements data structure that represents GFF3 formatted
// (http://www.sequenceontology.org/gff3.shtml) data, as well as Reader
// and Writer for this data
//
// Some code inspired by the golang standard library's csv package
package gff3

// Imports
// standard library
import (
	"bufio"
	"bytes"
	"io"
	"log"
	"strconv"
	"strings"
)

// A Reader reads records from a GFF3-formatted file
//
// As returned by NewReader, a Reader expects input to conform to
// http://www.sequenceontology.org/gff3.shtml
//
// As presently (2016-06-20) implemented, there may be some
// GENCODE or Ensembl specific attributes expected hereunder
//
// TODO: copy similar boilerplate from golang.org/src/encoding/csv/reader.go
//
type Reader struct {
	s      *bufio.Scanner
	line   int
	column int
	field  bytes.Buffer
}

// NewReader returns a new Reader that reads from r
// This is simply a wrapper to buffer input io.Reader if not already buffered
// also use the Scanner which is apparently idiomatic way to read lines now
func NewReader(r io.Reader) *Reader {
	return &Reader{
		s: bufio.NewScanner(r), // buffer input
	}
}

func (r *Reader) Read() (record *Record, err error) {
	// parseRecord one at a time, but retry if nil record (e.g. comment)
	for {
		record, err = r.parseRecord()
		// nil record, nil error could represent a comment line
		if record != nil {
			break
		}
		if err != nil {
			return nil, err
		}
	}
	return record, nil
}

// func (r *Reader) ReadAll() (records []Record, err error)

// parseRecord parses the elements of a single row into a GFF3 struct
func (r *Reader) parseRecord() (rec *Record, err error) {
	// line numbering starts with 1, not 0, so increment straightaway
	r.line++
	_ = r.s.Scan() // read a line

	// Examine first byte -- if comment, skip this row
	if r.s.Bytes()[0] == '#' {
		return nil, nil // no record, no error
		// returning nil might break Filtering which expects *Record
		// however I think the for {} loop in Read() will keep looking
		// for a valid record
	}

	// I don't think I need to strip trailing newline

	// split into fields
	// this will allocate a new string and a new array (2 alloc/op)
	fields := strings.Split(r.s.Text(), "\t")
	if len(fields) != 9 {
		// comment lines should have already been dealt with,
		// so this is a malformed record
		log.Fatalln("Malformed record: ", r.s.Text())
	}

	rec = new(Record)
	rec.seqidField = fields[0]
	rec.sourceField = fields[1]
	rec.typeField = fields[2]
	rec.startField, _ = strconv.Atoi(fields[3])
	rec.endField, _ = strconv.Atoi(fields[4])
	rec.scoreField, _ = strconv.ParseFloat(fields[5], 64)
	rec.strandField = fields[6][0] // one byte char: +, -, ., or ?
	rec.phaseField, _ = strconv.Atoi(fields[7])
	// must initialize the nil map or face a runtime panic
	rec.attributesField = make(map[string]string)
	for _, attribute := range strings.Split(fields[8], ";") {
		kv := strings.Split(attribute, "=")
		key := k[0]
		value := v[1]
		rec.attributesField[key] = value
	}

	// validate is currently stub function always true
	if rec.validate() {
		rec.Complete = true
		return rec, nil
	} else {
		// need to return an error also
		return rec, nil
	}
}

// loads a GFF3 record from a line of input into the Record struct
// Wrote this before conversion to Reader object
// deprecated - prefixed with x to avoid export
/*
func xLoadRecord(line string) *Record {
	// ignore comment lines
	if line[0] == '#' {
		return new(Record)
	}

	// strip trailing newline, if any
	line = strings.TrimSuffix(line, "\n")

	// split into fields
	fields := strings.Split(line, "\t")
	if len(fields) != 9 {
		// comment lines should already have been dealt with,
		// so this is a malformed record
		log.Fatalln("Malformed record: ", line)
	}

	r := new(Record)
	r.seqidField = fields[0]
	r.sourceField = fields[1]
	r.typeField = fields[2]
	r.startField, _ = strconv.Atoi(fields[3])
	r.endField, _ = strconv.Atoi(fields[4])
	r.scoreField, _ = strconv.ParseFloat(fields[5], 64)
	r.strandField = fields[6][0] // one byte char: +, -, ., or ?
	r.phaseField, _ = strconv.Atoi(fields[7])
	//r.attributesField = fields[8]

	// validate is currently stub function always true
	if r.validate() {
		r.Complete = true
		return r
	} else {
		// need to return an error also
		return r
	}
}
*/
<commit_msg>comment for future optimization<commit_after>// Package gff3 implements data structure that represents GFF3 formatted
// (http://www.sequenceontology.org/gff3.shtml) data, as well as Reader
// and Writer for this data
//
// Some code inspired by the golang standard library's csv package
package gff3

// Imports
// standard library
import (
	"bufio"
	"bytes"
	"io"
	"log"
	"strconv"
	"strings"
)

// A Reader reads records from a GFF3-formatted file
//
// As returned by NewReader, a Reader expects input to conform to
// http://www.sequenceontology.org/gff3.shtml
//
// As presently (2016-06-20) implemented, there may be some
// GENCODE or Ensembl specific attributes expected hereunder
//
// TODO: copy similar boilerplate from golang.org/src/encoding/csv/reader.go
//
type Reader struct {
	s      *bufio.Scanner
	line   int
	column int
	field  bytes.Buffer
}

// NewReader returns a new Reader that reads from r
// This is simply a wrapper to buffer input io.Reader if not already buffered
// also use the Scanner which is apparently idiomatic way to read lines now
func NewReader(r io.Reader) *Reader {
	return &Reader{
		s: bufio.NewScanner(r), // buffer input
	}
}

func (r *Reader) Read() (record *Record, err error) {
	// parseRecord one at a time, but retry if nil record (e.g. comment)
	for {
		record, err = r.parseRecord()
		// nil record, nil error could represent a comment line
		if record != nil {
			break
		}
		if err != nil {
			return nil, err
		}
	}
	return record, nil
}

// func (r *Reader) ReadAll() (records []Record, err error)

// parseRecord parses the elements of a single row into a GFF3 struct
func (r *Reader) parseRecord() (rec *Record, err error) {
	// line numbering starts with 1, not 0, so increment straightaway
	r.line++
	_ = r.s.Scan() // read a line

	// Examine first byte -- if comment, skip this row
	if r.s.Bytes()[0] == '#' {
		return nil, nil // no record, no error
		// returning nil might break Filtering which expects *Record
		// however I think the for {} loop in Read() will keep looking
		// for a valid record
	}

	// I don't think I need to strip trailing newline

	// split into fields
	// this will allocate a new string and a new array (2 alloc/op)
	fields := strings.Split(r.s.Text(), "\t")
	if len(fields) != 9 {
		// comment lines should have already been dealt with,
		// so this is a malformed record
		log.Fatalln("Malformed record: ", r.s.Text())
	}

	rec = new(Record)
	rec.seqidField = fields[0]
	rec.sourceField = fields[1]
	rec.typeField = fields[2]
	rec.startField, _ = strconv.Atoi(fields[3])
	rec.endField, _ = strconv.Atoi(fields[4])
	rec.scoreField, _ = strconv.ParseFloat(fields[5], 64)
	rec.strandField = fields[6][0] // one byte char: +, -, ., or ?
	rec.phaseField, _ = strconv.Atoi(fields[7])
	// must initialize the nil map or face a runtime panic
	rec.attributesField = make(map[string]string)
	for _, attribute := range strings.Split(fields[8], ";") {
		kv := strings.Split(attribute, "=")
		key := k[0]
		value := v[1]
		// TODO remove key, value allocs see if speed increase
		rec.attributesField[key] = value
	}

	// validate is currently stub function always true
	if rec.validate() {
		rec.Complete = true
		return rec, nil
	} else {
		// need to return an error also
		return rec, nil
	}
}

// loads a GFF3 record from a line of input into the Record struct
// Wrote this before conversion to Reader object
// deprecated - prefixed with x to avoid export
/*
func xLoadRecord(line string) *Record {
	// ignore comment lines
	if line[0] == '#' {
		return new(Record)
	}

	// strip trailing newline, if any
	line = strings.TrimSuffix(line, "\n")

	// split into fields
	fields := strings.Split(line, "\t")
	if len(fields) != 9 {
		// comment lines should already have been dealt with,
		// so this is a malformed record
		log.Fatalln("Malformed record: ", line)
	}

	r := new(Record)
	r.seqidField = fields[0]
	r.sourceField = fields[1]
	r.typeField = fields[2]
	r.startField, _ = strconv.Atoi(fields[3])
	r.endField, _ = strconv.Atoi(fields[4])
	r.scoreField, _ = strconv.ParseFloat(fields[5], 64)
	r.strandField = fields[6][0] // one byte char: +, -, ., or ?
	r.phaseField, _ = strconv.Atoi(fields[7])
	//r.attributesField = fields[8]

	// validate is currently stub function always true
	if r.validate() {
		r.Complete = true
		return r
	} else {
		// need to return an error also
		return r
	}
}
*/
<|endoftext|>