<commit_before>package mpa

import (
	"io"

	"github.com/korandiz/mpa"
	"github.com/mjibson/mog/codec"
)

func init() {
	exts := []string{"mp3"}
	codec.RegisterCodec("MP3", "\xff\xfa", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfb", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfc", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfd", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfe", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xff", exts, NewSongs)
}

func NewSongs(rf codec.Reader) ([]codec.Song, error) {
	s, err := NewSong(rf)
	if err != nil {
		return nil, err
	}
	return []codec.Song{s}, nil
}

type Song struct {
	Reader  codec.Reader
	r       io.ReadCloser
	decoder *mpa.Decoder
	buff    [2][]float32
}

func NewSong(rf codec.Reader) (*Song, error) {
	s := &Song{Reader: rf}
	_, _, err := s.Init()
	return s, err
}

func (s *Song) Init() (sampleRate, channels int, err error) {
	if s.decoder == nil {
		r, _, err := s.Reader()
		if err != nil {
			return 0, 0, err
		}
		s.decoder = &mpa.Decoder{Input: r}
		s.r = r
		if err := s.decoder.DecodeFrame(); err != nil {
			r.Close()
			return 0, 0, err
		}
	}
	return s.decoder.SamplingFrequency(), s.decoder.NChannels(), nil
}

func (s *Song) Info() (codec.SongInfo, error) {
	return codec.SongInfo{}, nil
}

func (s *Song) Play(n int) (r []float32, err error) {
	for len(r) < n {
		if len(s.buff[0]) == 0 {
			if err = s.decoder.DecodeFrame(); err != nil {
				return
			}
			for i := 0; i < 2; i++ {
				s.buff[i] = make([]float32, s.decoder.NSamples())
				s.decoder.ReadSamples(i, s.buff[i])
			}
		}
		for len(s.buff[0]) > 0 && len(r) < n {
			r = append(r, s.buff[0][0], s.buff[1][0])
			s.buff[0], s.buff[1] = s.buff[0][1:], s.buff[1][1:]
		}
	}
	return
}

func (s *Song) Close() {
	if s.r != nil {
		s.r.Close()
	}
	s.decoder, s.buff[0], s.buff[1], s.r = nil, nil, nil, nil
}
<commit_msg>Ignore malformed MP3 frames<commit_after>package mpa

import (
	"io"

	"github.com/korandiz/mpa"
	"github.com/mjibson/mog/codec"
)

func init() {
	exts := []string{"mp3"}
	codec.RegisterCodec("MP3", "\xff\xfa", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfb", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfc", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfd", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xfe", exts, NewSongs)
	codec.RegisterCodec("MP3", "\xff\xff", exts, NewSongs)
}

func NewSongs(rf codec.Reader) ([]codec.Song, error) {
	s, err := NewSong(rf)
	if err != nil {
		return nil, err
	}
	return []codec.Song{s}, nil
}

type Song struct {
	Reader  codec.Reader
	r       io.ReadCloser
	decoder *mpa.Decoder
	buff    [2][]float32
}

func NewSong(rf codec.Reader) (*Song, error) {
	s := &Song{Reader: rf}
	_, _, err := s.Init()
	return s, err
}

func (s *Song) Init() (sampleRate, channels int, err error) {
	if s.decoder == nil {
		r, _, err := s.Reader()
		if err != nil {
			return 0, 0, err
		}
		s.decoder = &mpa.Decoder{Input: r}
		s.r = r
		for {
			if err := s.decoder.DecodeFrame(); err != nil {
				switch err.(type) {
				case mpa.MalformedStream:
					continue
				}
				r.Close()
				return 0, 0, err
			}
			break
		}
	}
	return s.decoder.SamplingFrequency(), s.decoder.NChannels(), nil
}

func (s *Song) Info() (codec.SongInfo, error) {
	return codec.SongInfo{}, nil
}

func (s *Song) Play(n int) (r []float32, err error) {
	for len(r) < n {
		if len(s.buff[0]) == 0 {
			err = s.decoder.DecodeFrame()
			if err != nil {
				switch err.(type) {
				case mpa.MalformedStream:
					continue
				}
				return
			}
			for i := 0; i < 2; i++ {
				s.buff[i] = make([]float32, s.decoder.NSamples())
				s.decoder.ReadSamples(i, s.buff[i])
			}
		}
		for len(s.buff[0]) > 0 && len(r) < n {
			r = append(r, s.buff[0][0], s.buff[1][0])
			s.buff[0], s.buff[1] = s.buff[0][1:], s.buff[1][1:]
		}
	}
	return
}

func (s *Song) Close() {
	if s.r != nil {
		s.r.Close()
	}
	s.decoder, s.buff[0], s.buff[1], s.r = nil, nil, nil, nil
}
<|endoftext|>


<commit_before>package ethchain

import (
	"bytes"
	"fmt"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/ethereum/eth-go/ethwire"
	"math/big"
	"sync"
	"time"
)

type BlockProcessor interface {
	ProcessBlock(block *Block)
}

type EthManager interface {
	StateManager() *StateManager
	BlockChain() *BlockChain
	TxPool() *TxPool
	Broadcast(msgType ethwire.MsgType, data []interface{})
	Reactor() *ethutil.ReactorEngine
}

type StateManager struct {
	// Mutex for locking the block processor. Blocks can only be handled one at a time
	mutex sync.Mutex

	// Canonical block chain
	bc *BlockChain
	// States for addresses. You can watch any address
	// at any given time
	addrStateStore *AddrStateStore

	// Stack for processing contracts
	stack *Stack
	// non-persistent key/value memory storage
	mem map[string]*big.Int

	Pow PoW

	Ethereum EthManager

	SecondaryBlockProcessor BlockProcessor

	// The managed states
	// Processor state. Anything processed will be applied to this
	// state
	procState *State
	// Comparative state it used for comparing and validating end
	// results
	compState *State
}

func NewStateManager(ethereum EthManager) *StateManager {
	sm := &StateManager{
		stack:          NewStack(),
		mem:            make(map[string]*big.Int),
		Pow:            &EasyPow{},
		Ethereum:       ethereum,
		addrStateStore: NewAddrStateStore(),
		bc:             ethereum.BlockChain(),
	}
	sm.procState = ethereum.BlockChain().CurrentBlock.State()
	return sm
}

func (sm *StateManager) ProcState() *State {
	return sm.procState
}

// Watches any given address and puts it in the address state store
func (sm *StateManager) WatchAddr(addr []byte) *AccountState {
	//XXX account := sm.bc.CurrentBlock.state.GetAccount(addr)
	account := sm.procState.GetAccount(addr)

	return sm.addrStateStore.Add(addr, account)
}

func (sm *StateManager) GetAddrState(addr []byte) *AccountState {
	account := sm.addrStateStore.Get(addr)
	if account == nil {
		a := sm.procState.GetAccount(addr)
		account = &AccountState{Nonce: a.Nonce, Account: a}
	}

	return account
}

func (sm *StateManager) BlockChain() *BlockChain {
	return sm.bc
}

func (sm *StateManager) MakeContract(tx *Transaction) {
	contract := MakeContract(tx, sm.procState)
	if contract != nil {
		sm.procState.states[string(tx.Hash()[12:])] = contract.state
	}
}

// Apply transactions uses the transaction passed to it and applies them onto
// the current processing state.
func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
	// Process each transaction/contract
	for _, tx := range txs {
		// If there's no recipient, it's a contract
		// Check if this is a contract creation traction and if so
		// create a contract of this tx.
		if tx.IsContract() {
			sm.MakeContract(tx)
		} else {
			// Figure out if the address this transaction was sent to is a
			// contract or an actual account. In case of a contract, we process that
			// contract instead of moving funds between accounts.
			var err error
			if contract := sm.procState.GetContract(tx.Recipient); contract != nil {
				err = sm.Ethereum.TxPool().ProcessTransaction(tx, block, true)
				if err == nil {
					sm.ProcessContract(contract, tx, block)
				}
			} else {
				err = sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
			}

			if err != nil {
				ethutil.Config.Log.Infoln("[STATE]", err)
			}
		}
	}
}

// The prepare function, prepares the state manager for the next
// "ProcessBlock" action.
func (sm *StateManager) Prepare(processor *State, comparative *State) {
	sm.compState = comparative
	sm.procState = processor
}

// Default prepare function
func (sm *StateManager) PrepareDefault(block *Block) {
	sm.Prepare(sm.BlockChain().CurrentBlock.State(), block.State())
}

// Block processing and validating with a given (temporarily) state
func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
	// Processing a blocks may never happen simultaneously
	sm.mutex.Lock()
	defer sm.mutex.Unlock()
	// Defer the Undo on the Trie. If the block processing happened
	// we don't want to undo but since undo only happens on dirty
	// nodes this won't happen because Commit would have been called
	// before that.
	defer sm.bc.CurrentBlock.Undo()
	hash := block.Hash()

	if sm.bc.HasBlock(hash) {
		fmt.Println("[SM] We already have this block, ignoring")
		return nil
	}

	// Check if we have the parent hash, if it isn't known we discard it
	// Reasons might be catching up or simply an invalid block
	if !sm.bc.HasBlock(block.PrevHash) && sm.bc.CurrentBlock != nil {
		return ParentError(block.PrevHash)
	}

	// Process the transactions on to current block
	sm.ApplyTransactions(sm.bc.CurrentBlock, block.Transactions())

	// Block validation
	if err := sm.ValidateBlock(block); err != nil {
		fmt.Println("[SM] Error validating block:", err)
		return err
	}

	// I'm not sure, but I don't know if there should be thrown
	// any errors at this time.
	if err := sm.AccumelateRewards(block); err != nil {
		fmt.Println("[SM] Error accumulating reward", err)
		return err
	}

	// if !sm.compState.Cmp(sm.procState)
	if !sm.compState.Cmp(sm.procState) {
		return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root)
	}

	// Calculate the new total difficulty and sync back to the db
	if sm.CalculateTD(block) {
		// Sync the current block's state to the database and cancelling out the deferred Undo
		sm.procState.Sync()

		// Broadcast the valid block back to the wire
		//sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})

		// Add the block to the chain
		sm.bc.Add(block)

		// If there's a block processor present, pass in the block for further
		// processing
		if sm.SecondaryBlockProcessor != nil {
			sm.SecondaryBlockProcessor.ProcessBlock(block)
		}

		ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash())
		if dontReact == false {
			sm.Ethereum.Reactor().Post("newBlock", block)
		}
	} else {
		fmt.Println("total diff failed")
	}

	return nil
}
func (sm *StateManager) CalculateTD(block *Block) bool {
	uncleDiff := new(big.Int)
	for _, uncle := range block.Uncles {
		uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
	}

	// TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
	td := new(big.Int)
	td = td.Add(sm.bc.TD, uncleDiff)
	td = td.Add(td, block.Difficulty)

	// The new TD will only be accepted if the new difficulty is
	// is greater than the previous.
	if td.Cmp(sm.bc.TD) > 0 {
		// Set the new total difficulty back to the block chain
		sm.bc.SetTotalDifficulty(td)

		return true
	}

	return false
}

// Validates the current block. Returns an error if the block was invalid,
// an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult)
func (sm *StateManager) ValidateBlock(block *Block) error {
	// TODO
	// 2. Check if the difficulty is correct

	// Check each uncle's previous hash. In order for it to be valid
	// is if it has the same block hash as the current
	previousBlock := sm.bc.GetBlock(block.PrevHash)
	for _, uncle := range block.Uncles {
		if bytes.Compare(uncle.PrevHash, previousBlock.PrevHash) != 0 {
			return ValidationError("Mismatch uncle's previous hash. Expected %x, got %x", previousBlock.PrevHash, uncle.PrevHash)
		}
	}

	diff := block.Time - sm.bc.CurrentBlock.Time
	if diff < 0 {
		return ValidationError("Block timestamp less then prev block %v", diff)
	}

	// New blocks must be within the 15 minute range of the last block.
	if diff > int64(15*time.Minute) {
		return ValidationError("Block is too far in the future of last block (> 15 minutes)")
	}

	// Verify the nonce of the block. Return an error if it's not valid
	if !sm.Pow.Verify(block.HashNoNonce(), block.Difficulty, block.Nonce) {
		return ValidationError("Block's nonce is invalid (= %v)", ethutil.Hex(block.Nonce))
	}

	return nil
}

func CalculateBlockReward(block *Block, uncleLength int) *big.Int {
	base := new(big.Int)
	for i := 0; i < uncleLength; i++ {
		base.Add(base, UncleInclusionReward)
	}
	return base.Add(base, BlockReward)
}

func CalculateUncleReward(block *Block) *big.Int {
	return UncleReward
}

func (sm *StateManager) AccumelateRewards(block *Block) error {

	// Get the coinbase rlp data
	addr := sm.procState.GetAccount(block.Coinbase)
	// Reward amount of ether to the coinbase address
	addr.AddFee(CalculateBlockReward(block, len(block.Uncles)))

	acc := make([]byte, len(block.Coinbase))
	copy(acc, block.Coinbase)
	sm.procState.UpdateAccount(acc, addr)

	for _, uncle := range block.Uncles {
		uncleAddr := sm.procState.GetAccount(uncle.Coinbase)
		uncleAddr.AddFee(CalculateUncleReward(uncle))

		//processor.state.UpdateAccount(uncle.Coinbase, uncleAddr)
		sm.procState.UpdateAccount(uncle.Coinbase, uncleAddr)
	}

	return nil
}

func (sm *StateManager) Stop() {
	sm.bc.Stop()
}

func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, block *Block) {
	// Recovering function in case the VM had any errors
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from VM execution with err =", r)
		}
	}()

	caller := sm.procState.GetAccount(tx.Sender())
	closure := NewClosure(caller, contract, sm.procState, tx.Gas, tx.Value)
	vm := NewVm(sm.procState, RuntimeVars{
		origin:      caller.Address(),
		blockNumber: block.BlockInfo().Number,
		prevHash:    block.PrevHash,
		coinbase:    block.Coinbase,
		time:        block.Time,
		diff:        block.Difficulty,
		// XXX Tx data? Could be just an argument to the closure instead
		txData: nil,
	})
	closure.Call(vm, nil)

	// Update the account (refunds)
	sm.procState.UpdateAccount(tx.Sender(), caller)
}
<commit_msg>Switched variable names<commit_after>package ethchain

import (
	"bytes"
	"fmt"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/ethereum/eth-go/ethwire"
	"math/big"
	"sync"
	"time"
)

type BlockProcessor interface {
	ProcessBlock(block *Block)
}

type EthManager interface {
	StateManager() *StateManager
	BlockChain() *BlockChain
	TxPool() *TxPool
	Broadcast(msgType ethwire.MsgType, data []interface{})
	Reactor() *ethutil.ReactorEngine
}

type StateManager struct {
	// Mutex for locking the block processor. Blocks can only be handled one at a time
	mutex sync.Mutex

	// Canonical block chain
	bc *BlockChain
	// States for addresses. You can watch any address
	// at any given time
	addrStateStore *AddrStateStore

	// Stack for processing contracts
	stack *Stack
	// non-persistent key/value memory storage
	mem map[string]*big.Int

	Pow PoW

	Ethereum EthManager

	SecondaryBlockProcessor BlockProcessor

	// The managed states
	// Processor state. Anything processed will be applied to this
	// state
	procState *State
	// Comparative state it used for comparing and validating end
	// results
	compState *State
}

func NewStateManager(ethereum EthManager) *StateManager {
	sm := &StateManager{
		stack:          NewStack(),
		mem:            make(map[string]*big.Int),
		Pow:            &EasyPow{},
		Ethereum:       ethereum,
		addrStateStore: NewAddrStateStore(),
		bc:             ethereum.BlockChain(),
	}
	sm.procState = ethereum.BlockChain().CurrentBlock.State()
	return sm
}

func (sm *StateManager) ProcState() *State {
	return sm.procState
}

// Watches any given address and puts it in the address state store
func (sm *StateManager) WatchAddr(addr []byte) *AccountState {
	//XXX account := sm.bc.CurrentBlock.state.GetAccount(addr)
	account := sm.procState.GetAccount(addr)

	return sm.addrStateStore.Add(addr, account)
}

func (sm *StateManager) GetAddrState(addr []byte) *AccountState {
	account := sm.addrStateStore.Get(addr)
	if account == nil {
		a := sm.procState.GetAccount(addr)
		account = &AccountState{Nonce: a.Nonce, Account: a}
	}

	return account
}

func (sm *StateManager) BlockChain() *BlockChain {
	return sm.bc
}

func (sm *StateManager) MakeContract(tx *Transaction) {
	contract := MakeContract(tx, sm.procState)
	if contract != nil {
		sm.procState.states[string(tx.Hash()[12:])] = contract.state
	}
}

// Apply transactions uses the transaction passed to it and applies them onto
// the current processing state.
func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
	// Process each transaction/contract
	for _, tx := range txs {
		// If there's no recipient, it's a contract
		// Check if this is a contract creation traction and if so
		// create a contract of this tx.
		if tx.IsContract() {
			sm.MakeContract(tx)
		} else {
			// Figure out if the address this transaction was sent to is a
			// contract or an actual account. In case of a contract, we process that
			// contract instead of moving funds between accounts.
			var err error
			if contract := sm.procState.GetContract(tx.Recipient); contract != nil {
				err = sm.Ethereum.TxPool().ProcessTransaction(tx, block, true)
				if err == nil {
					sm.ProcessContract(contract, tx, block)
				}
			} else {
				err = sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
			}

			if err != nil {
				ethutil.Config.Log.Infoln("[STATE]", err)
			}
		}
	}
}

// The prepare function, prepares the state manager for the next
// "ProcessBlock" action.
func (sm *StateManager) Prepare(processor *State, comparative *State) {
	sm.compState = comparative
	sm.procState = processor
}

// Default prepare function
func (sm *StateManager) PrepareDefault(block *Block) {
	sm.Prepare(sm.BlockChain().CurrentBlock.State(), block.State())
}

// Block processing and validating with a given (temporarily) state
func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
	// Processing a blocks may never happen simultaneously
	sm.mutex.Lock()
	defer sm.mutex.Unlock()
	// Defer the Undo on the Trie. If the block processing happened
	// we don't want to undo but since undo only happens on dirty
	// nodes this won't happen because Commit would have been called
	// before that.
	defer sm.bc.CurrentBlock.Undo()
	hash := block.Hash()

	if sm.bc.HasBlock(hash) {
		fmt.Println("[SM] We already have this block, ignoring")
		return nil
	}

	// Check if we have the parent hash, if it isn't known we discard it
	// Reasons might be catching up or simply an invalid block
	if !sm.bc.HasBlock(block.PrevHash) && sm.bc.CurrentBlock != nil {
		return ParentError(block.PrevHash)
	}

	// Process the transactions on to current block
	sm.ApplyTransactions(sm.bc.CurrentBlock, block.Transactions())

	// Block validation
	if err := sm.ValidateBlock(block); err != nil {
		fmt.Println("[SM] Error validating block:", err)
		return err
	}

	// I'm not sure, but I don't know if there should be thrown
	// any errors at this time.
	if err := sm.AccumelateRewards(block); err != nil {
		fmt.Println("[SM] Error accumulating reward", err)
		return err
	}

	// if !sm.compState.Cmp(sm.procState)
	if !sm.compState.Cmp(sm.procState) {
		return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root)
	}

	// Calculate the new total difficulty and sync back to the db
	if sm.CalculateTD(block) {
		// Sync the current block's state to the database and cancelling out the deferred Undo
		sm.procState.Sync()

		// Broadcast the valid block back to the wire
		//sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})

		// Add the block to the chain
		sm.bc.Add(block)

		// If there's a block processor present, pass in the block for further
		// processing
		if sm.SecondaryBlockProcessor != nil {
			sm.SecondaryBlockProcessor.ProcessBlock(block)
		}

		ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash())
		if dontReact == false {
			sm.Ethereum.Reactor().Post("newBlock", block)
		}
	} else {
		fmt.Println("total diff failed")
	}

	return nil
}
func (sm *StateManager) CalculateTD(block *Block) bool {
	uncleDiff := new(big.Int)
	for _, uncle := range block.Uncles {
		uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
	}

	// TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
	td := new(big.Int)
	td = td.Add(sm.bc.TD, uncleDiff)
	td = td.Add(td, block.Difficulty)

	// The new TD will only be accepted if the new difficulty is
	// is greater than the previous.
	if td.Cmp(sm.bc.TD) > 0 {
		// Set the new total difficulty back to the block chain
		sm.bc.SetTotalDifficulty(td)

		return true
	}

	return false
}

// Validates the current block. Returns an error if the block was invalid,
// an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult)
func (sm *StateManager) ValidateBlock(block *Block) error {
	// TODO
	// 2. Check if the difficulty is correct

	// Check each uncle's previous hash. In order for it to be valid
	// is if it has the same block hash as the current
	previousBlock := sm.bc.GetBlock(block.PrevHash)
	for _, uncle := range block.Uncles {
		if bytes.Compare(uncle.PrevHash, previousBlock.PrevHash) != 0 {
			return ValidationError("Mismatch uncle's previous hash. Expected %x, got %x", previousBlock.PrevHash, uncle.PrevHash)
		}
	}

	diff := block.Time - sm.bc.CurrentBlock.Time
	if diff < 0 {
		return ValidationError("Block timestamp less then prev block %v", diff)
	}

	// New blocks must be within the 15 minute range of the last block.
	if diff > int64(15*time.Minute) {
		return ValidationError("Block is too far in the future of last block (> 15 minutes)")
	}

	// Verify the nonce of the block. Return an error if it's not valid
	if !sm.Pow.Verify(block.HashNoNonce(), block.Difficulty, block.Nonce) {
		return ValidationError("Block's nonce is invalid (= %v)", ethutil.Hex(block.Nonce))
	}

	return nil
}

func CalculateBlockReward(block *Block, uncleLength int) *big.Int {
	base := new(big.Int)
	for i := 0; i < uncleLength; i++ {
		base.Add(base, UncleInclusionReward)
	}
	return base.Add(base, BlockReward)
}

func CalculateUncleReward(block *Block) *big.Int {
	return UncleReward
}

func (sm *StateManager) AccumelateRewards(block *Block) error {

	// Get the coinbase rlp data
	acc := sm.procState.GetAccount(block.Coinbase)
	// Reward amount of ether to the coinbase address
	acc.AddFee(CalculateBlockReward(block, len(block.Uncles)))

	addr := make([]byte, len(block.Coinbase))
	copy(addr, block.Coinbase)
	sm.procState.UpdateAccount(addr, acc)

	for _, uncle := range block.Uncles {
		uncleAddr := sm.procState.GetAccount(uncle.Coinbase)
		uncleAddr.AddFee(CalculateUncleReward(uncle))

		//processor.state.UpdateAccount(uncle.Coinbase, uncleAddr)
		sm.procState.UpdateAccount(uncle.Coinbase, uncleAddr)
	}

	return nil
}

func (sm *StateManager) Stop() {
	sm.bc.Stop()
}

func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, block *Block) {
	// Recovering function in case the VM had any errors
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from VM execution with err =", r)
		}
	}()

	caller := sm.procState.GetAccount(tx.Sender())
	closure := NewClosure(caller, contract, sm.procState, tx.Gas, tx.Value)
	vm := NewVm(sm.procState, RuntimeVars{
		origin:      caller.Address(),
		blockNumber: block.BlockInfo().Number,
		prevHash:    block.PrevHash,
		coinbase:    block.Coinbase,
		time:        block.Time,
		diff:        block.Difficulty,
		// XXX Tx data? Could be just an argument to the closure instead
		txData: nil,
	})
	closure.Call(vm, nil)

	// Update the account (refunds)
	sm.procState.UpdateAccount(tx.Sender(), caller)
}
<|endoftext|>


<commit_before>// Copyright 2013 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.

// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package column

import (
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/util/types"
)

// Col provides meta data describing a table column.
type Col struct {
	model.ColumnInfo
}

// PrimaryKeyName defines primary key name.
const PrimaryKeyName = "PRIMARY"

// IndexedCol defines an index with info.
type IndexedCol struct {
	model.IndexInfo
	X kv.Index
}

// String implements fmt.Stringer interface.
func (c *Col) String() string {
	ans := []string{c.Name.O, types.TypeToStr(c.Tp, c.Charset)}
	if mysql.HasAutoIncrementFlag(c.Flag) {
		ans = append(ans, "AUTO_INCREMENT")
	}
	if mysql.HasNotNullFlag(c.Flag) {
		ans = append(ans, "NOT NULL")
	}
	return strings.Join(ans, " ")
}

// FindCol finds column in cols by name.
func FindCol(cols []*Col, name string) (c *Col) {
	for _, c := range cols {
		if strings.EqualFold(c.Name.O, name) {
			return
		}
	}
	return nil
}

// FindCols finds columns in cols by names.
func FindCols(cols []*Col, names []string) ([]*Col, error) {
	var rcols []*Col
	for _, name := range names {
		col := FindCol(cols, name)
		if col != nil {
			rcols = append(rcols, col)
		} else {
			return nil, errors.Errorf("unknown column %s", name)
		}
	}

	return rcols, nil
}

// FindOnUpdateCols finds columns which have OnUpdateNow flag.
func FindOnUpdateCols(cols []*Col) []*Col {
	var rcols []*Col
	for _, c := range cols {
		if mysql.HasOnUpdateNowFlag(c.Flag) {
			rcols = append(rcols, c)
		}
	}

	return rcols
}

// CastValues casts values based on columns type.
func CastValues(ctx context.Context, rec []interface{}, cols []*Col) (err error) {
	for _, c := range cols {
		rec[c.Offset], err = types.Convert(rec[c.Offset], &c.FieldType)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

// ColDesc describes column information like MySQL desc and show columns do.
type ColDesc struct {
	Field        string
	Type         string
	Collation    string
	Null         string
	Key          string
	DefaultValue interface{}
	Extra        string
	Privileges   string
	Comment      string
}

const defaultPrivileges string = "select,insert,update,references"

// GetTypeDesc gets the description for column type.
func (c *Col) GetTypeDesc() string {
	desc := c.FieldType.CompactStr()
	if mysql.HasUnsignedFlag(c.Flag) {
		desc += " UNSIGNED"
	}
	return desc
}

// NewColDesc returns a new ColDesc for a column.
func NewColDesc(col *Col) *ColDesc {
	// TODO: if we have no primary key and a unique index which's columns are all not null
	// we will set these columns' flag as PriKeyFlag
	// see https://dev.mysql.com/doc/refman/5.7/en/show-columns.html
	// create table
	name := col.Name
	nullFlag := "YES"
	if mysql.HasNotNullFlag(col.Flag) {
		nullFlag = "NO"
	}
	keyFlag := ""
	if mysql.HasPriKeyFlag(col.Flag) {
		keyFlag = "PRI"
	} else if mysql.HasUniKeyFlag(col.Flag) {
		keyFlag = "UNI"
	} else if mysql.HasMultipleKeyFlag(col.Flag) {
		keyFlag = "MUL"
	}
	var defaultValue interface{}
	if !mysql.HasNoDefaultValueFlag(col.Flag) {
		defaultValue = col.DefaultValue
	}

	extra := ""
	if mysql.HasAutoIncrementFlag(col.Flag) {
		extra = "auto_increment"
	} else if mysql.HasOnUpdateNowFlag(col.Flag) {
		extra = "on update CURRENT_TIMESTAMP"
	}

	return &ColDesc{
		Field:        name.O,
		Type:         col.GetTypeDesc(),
		Collation:    col.Collate,
		Null:         nullFlag,
		Key:          keyFlag,
		DefaultValue: defaultValue,
		Extra:        extra,
		Privileges:   defaultPrivileges,
		Comment:      "",
	}
}

// ColDescFieldNames returns the fields name in result set for desc and show columns.
func ColDescFieldNames(full bool) []string {
	if full {
		return []string{"Field", "Type", "Collation", "Null", "Key", "Default", "Extra", "Privileges", "Comment"}
	}
	return []string{"Field", "Type", "Null", "Key", "Default", "Extra"}
}

// CheckOnce checks if there are duplicated column names in cols.
func CheckOnce(cols []*Col) error {
	m := map[string]struct{}{}
	for _, v := range cols {
		name := v.Name
		_, ok := m[name.L]
		if ok {
			return errors.Errorf("column specified twice - %s", name)
		}

		m[name.L] = struct{}{}
	}

	return nil
}

// CheckNotNull checks if nil value set to a column with NotNull flag is set.
func (c *Col) CheckNotNull(data interface{}) error {
	if mysql.HasNotNullFlag(c.Flag) && data == nil {
		return errors.Errorf("Column %s can't be null.", c.Name)
	}
	return nil
}

// CheckNotNull checks if row has nil value set to a column with NotNull flag set.
func CheckNotNull(cols []*Col, row []interface{}) error {
	for _, c := range cols {
		if err := c.CheckNotNull(row[c.Offset]); err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

// FetchValues fetches indexed values from a row.
func (idx *IndexedCol) FetchValues(r []interface{}) ([]interface{}, error) {
	var vals []interface{}
	for _, ic := range idx.Columns {
		if ic.Offset < 0 || ic.Offset > len(r) {
			return nil, errors.New("Index column offset out of bound")
		}
		vals = append(vals, r[ic.Offset])
	}
	return vals, nil
}
<commit_msg>If we found c, then return c<commit_after>// Copyright 2013 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.

// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package column

import (
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/util/types"
)

// Col provides meta data describing a table column.
type Col struct {
	model.ColumnInfo
}

// PrimaryKeyName defines primary key name.
const PrimaryKeyName = "PRIMARY"

// IndexedCol defines an index with info.
type IndexedCol struct {
	model.IndexInfo
	X kv.Index
}

// String implements fmt.Stringer interface.
func (c *Col) String() string {
	ans := []string{c.Name.O, types.TypeToStr(c.Tp, c.Charset)}
	if mysql.HasAutoIncrementFlag(c.Flag) {
		ans = append(ans, "AUTO_INCREMENT")
	}
	if mysql.HasNotNullFlag(c.Flag) {
		ans = append(ans, "NOT NULL")
	}
	return strings.Join(ans, " ")
}

// FindCol finds column in cols by name.
func FindCol(cols []*Col, name string) (c *Col) {
	for _, c := range cols {
		if strings.EqualFold(c.Name.O, name) {
			return c
		}
	}
	return nil
}

// FindCols finds columns in cols by names.
func FindCols(cols []*Col, names []string) ([]*Col, error) {
	var rcols []*Col
	for _, name := range names {
		col := FindCol(cols, name)
		if col != nil {
			rcols = append(rcols, col)
		} else {
			return nil, errors.Errorf("unknown column %s", name)
		}
	}

	return rcols, nil
}

// FindOnUpdateCols finds columns which have OnUpdateNow flag.
func FindOnUpdateCols(cols []*Col) []*Col {
	var rcols []*Col
	for _, c := range cols {
		if mysql.HasOnUpdateNowFlag(c.Flag) {
			rcols = append(rcols, c)
		}
	}

	return rcols
}

// CastValues casts values based on columns type.
func CastValues(ctx context.Context, rec []interface{}, cols []*Col) (err error) {
	for _, c := range cols {
		rec[c.Offset], err = types.Convert(rec[c.Offset], &c.FieldType)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

// ColDesc describes column information like MySQL desc and show columns do.
type ColDesc struct {
	Field        string
	Type         string
	Collation    string
	Null         string
	Key          string
	DefaultValue interface{}
	Extra        string
	Privileges   string
	Comment      string
}

const defaultPrivileges string = "select,insert,update,references"

// GetTypeDesc gets the description for column type.
func (c *Col) GetTypeDesc() string {
	desc := c.FieldType.CompactStr()
	if mysql.HasUnsignedFlag(c.Flag) {
		desc += " UNSIGNED"
	}
	return desc
}

// NewColDesc returns a new ColDesc for a column.
func NewColDesc(col *Col) *ColDesc {
	// TODO: if we have no primary key and a unique index which's columns are all not null
	// we will set these columns' flag as PriKeyFlag
	// see https://dev.mysql.com/doc/refman/5.7/en/show-columns.html
	// create table
	name := col.Name
	nullFlag := "YES"
	if mysql.HasNotNullFlag(col.Flag) {
		nullFlag = "NO"
	}
	keyFlag := ""
	if mysql.HasPriKeyFlag(col.Flag) {
		keyFlag = "PRI"
	} else if mysql.HasUniKeyFlag(col.Flag) {
		keyFlag = "UNI"
	} else if mysql.HasMultipleKeyFlag(col.Flag) {
		keyFlag = "MUL"
	}
	var defaultValue interface{}
	if !mysql.HasNoDefaultValueFlag(col.Flag) {
		defaultValue = col.DefaultValue
	}

	extra := ""
	if mysql.HasAutoIncrementFlag(col.Flag) {
		extra = "auto_increment"
	} else if mysql.HasOnUpdateNowFlag(col.Flag) {
		extra = "on update CURRENT_TIMESTAMP"
	}

	return &ColDesc{
		Field:        name.O,
		Type:         col.GetTypeDesc(),
		Collation:    col.Collate,
		Null:         nullFlag,
		Key:          keyFlag,
		DefaultValue: defaultValue,
		Extra:        extra,
		Privileges:   defaultPrivileges,
		Comment:      "",
	}
}

// ColDescFieldNames returns the fields name in result set for desc and show columns.
func ColDescFieldNames(full bool) []string {
	if full {
		return []string{"Field", "Type", "Collation", "Null", "Key", "Default", "Extra", "Privileges", "Comment"}
	}
	return []string{"Field", "Type", "Null", "Key", "Default", "Extra"}
}

// CheckOnce checks if there are duplicated column names in cols.
func CheckOnce(cols []*Col) error {
	m := map[string]struct{}{}
	for _, v := range cols {
		name := v.Name
		_, ok := m[name.L]
		if ok {
			return errors.Errorf("column specified twice - %s", name)
		}

		m[name.L] = struct{}{}
	}

	return nil
}

// CheckNotNull checks if nil value set to a column with NotNull flag is set.
func (c *Col) CheckNotNull(data interface{}) error {
	if mysql.HasNotNullFlag(c.Flag) && data == nil {
		return errors.Errorf("Column %s can't be null.", c.Name)
	}
	return nil
}

// CheckNotNull checks if row has nil value set to a column with NotNull flag set.
func CheckNotNull(cols []*Col, row []interface{}) error {
	for _, c := range cols {
		if err := c.CheckNotNull(row[c.Offset]); err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}

// FetchValues fetches indexed values from a row.
func (idx *IndexedCol) FetchValues(r []interface{}) ([]interface{}, error) {
	var vals []interface{}
	for _, ic := range idx.Columns {
		if ic.Offset < 0 || ic.Offset > len(r) {
			return nil, errors.New("Index column offset out of bound")
		}
		vals = append(vals, r[ic.Offset])
	}
	return vals, nil
}
<|endoftext|>


<commit_before>package command

import (
	"bufio"
	"fmt"
	"log"
	"regexp"
	"strconv"
	"strings"

	"github.com/go-almeria/gitx/api"
	"github.com/go-almeria/gitx/meta"
)

// CountCommand Outputs commit count
type CountCommand struct {
	meta.Meta
}

func (c *CountCommand) Run(args []string) int {
	var all bool

	flags := c.Meta.FlagSet("count", meta.FlagSetDefault)
	flags.BoolVar(&all, "all", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) > 1 {
		flags.Usage()
		c.Ui.Error(fmt.Sprintf("\ncount expects at most one argument"))
		return 1
	}

	g := *api.NewGit("shortlog HEAD -n -s")
	if err := g.Run(); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", string(g.Err.Bytes())))
		return 1
	}

	re := regexp.MustCompile(`(\d+)\s+(\S+.*)`)
	scanner := bufio.NewScanner(&g.Out)

	count := 0
	for scanner.Scan() {
		results := re.FindAllStringSubmatch(scanner.Text(), -1)
		userCount, _ := strconv.Atoi(results[0][1])
		count += userCount
		user := results[0][2]
		if all {
			fmt.Printf("%s (%d)\n", user, userCount)
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatal("--->", err)
	}
	fmt.Printf("\ntotal %d\n", count)

	return 0
}

func (c *CountCommand) Synopsis() string {
	return "Outputs commit counts"
}

func (c *CountCommand) Help() string {
	helpText := `
Usage: gitx count [--all]
`
	return strings.TrimSpace(helpText)
}
<commit_msg>Messages to Ui<commit_after>package command

import (
	"bufio"
	"fmt"
	"log"
	"regexp"
	"strconv"
	"strings"

	"github.com/go-almeria/gitx/api"
	"github.com/go-almeria/gitx/meta"
)

// CountCommand Outputs commit count
type CountCommand struct {
	meta.Meta
}

func (c *CountCommand) Run(args []string) int {
	var all bool

	flags := c.Meta.FlagSet("count", meta.FlagSetDefault)
	flags.BoolVar(&all, "all", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) > 1 {
		flags.Usage()
		c.Ui.Error(fmt.Sprintf("\ncount expects at most one argument"))
		return 1
	}

	g := *api.NewGit("shortlog HEAD -n -s")
	if err := g.Run(); err != nil {
		c.Ui.Error(fmt.Sprintf("%s", string(g.Err.Bytes())))
		return 1
	}

	re := regexp.MustCompile(`(\d+)\s+(\S+.*)`)
	scanner := bufio.NewScanner(&g.Out)

	count := 0
	for scanner.Scan() {
		results := re.FindAllStringSubmatch(scanner.Text(), -1)
		userCount, _ := strconv.Atoi(results[0][1])
		count += userCount
		user := results[0][2]
		if all {
			c.Ui.Info(fmt.Sprintf("%s (%d)", user, userCount))
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatal("--->", err)
	}
	c.Ui.Info(fmt.Sprintf("\ntotal %d", count))

	return 0
}

func (c *CountCommand) Synopsis() string {
	return "Outputs commit counts"
}

func (c *CountCommand) Help() string {
	helpText := `
Usage: gitx count [--all]
`
	return strings.TrimSpace(helpText)
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"strconv"

	"github.com/alexhokl/go-bb-pr/git"
	"github.com/spf13/cobra"
)

type mergeOptions struct {
	isKeepBranch bool
}

// NewMergeCommand returns definition of command merge
func NewMergeCommand(cli *ManagerCli) *cobra.Command {
	opts := mergeOptions{}

	cmd := &cobra.Command{
		Use:   "merge [PR ID]",
		Short: "Merge a pull request",
		RunE: func(cmd *cobra.Command, args []string) error {
			return runMerge(cli, args)
		},
	}

	flags := cmd.Flags()
	flags.BoolVarP(&opts.isKeepBranch, "keep-branch", "k", false, "Keep local branch after merging")

	return cmd
}

func runMerge(cli *ManagerCli, args []string) error {
	client := cli.Client()
	cred := cli.UserCredential()
	repo := cli.Repo()
	pullRequestNumber, errParse := strconv.Atoi(args[0])
	if errParse != nil {
		return errParse
	}

	pr, errGet := client.GetRequest(cred, repo, pullRequestNumber)
	if errGet != nil {
		return errGet
	}

	err := client.MergeRequest(cred, repo, pullRequestNumber)
	if err != nil {
		return err
	}
	fmt.Printf("Merged pull request [%d].\n", pullRequestNumber)

	currentBranchName, errCurrentBranch := git.GetCurrentBranchName()
	if errCurrentBranch != nil {
		return errCurrentBranch
	}

	if currentBranchName == pr.Source.Branch.Name {
		_, errCheckout := git.Checkout(pr.Destination.Branch.Name)
		if errCheckout != nil {
			return errCheckout
		}
		fmt.Printf("Checked out to branch %s.", pr.Destination.Branch.Name)
	}

	_, errDelete := git.DeleteBranch(pr.Source.Branch.Name)
	if errDelete != nil {
		return errDelete
	}
	fmt.Printf("Deleted branch %s.", pr.Source.Branch.Name)

	return nil
}
<commit_msg>Added keep branch option to merge command<commit_after>package command

import (
	"fmt"
	"strconv"

	"github.com/alexhokl/go-bb-pr/git"
	"github.com/spf13/cobra"
)

type mergeOptions struct {
	isKeepBranch bool
}

// NewMergeCommand returns definition of command merge
func NewMergeCommand(cli *ManagerCli) *cobra.Command {
	opts := mergeOptions{}

	cmd := &cobra.Command{
		Use:   "merge [PR ID]",
		Short: "Merge a pull request",
		RunE: func(cmd *cobra.Command, args []string) error {
			return runMerge(cli, args, opts)
		},
	}

	flags := cmd.Flags()
	flags.BoolVarP(&opts.isKeepBranch, "keep-branch", "k", false, "Keep local branch after merging")

	return cmd
}

func runMerge(cli *ManagerCli, args []string, opts mergeOptions) error {
	client := cli.Client()
	cred := cli.UserCredential()
	repo := cli.Repo()
	pullRequestNumber, errParse := strconv.Atoi(args[0])
	if errParse != nil {
		return errParse
	}

	pr, errGet := client.GetRequest(cred, repo, pullRequestNumber)
	if errGet != nil {
		return errGet
	}

	err := client.MergeRequest(cred, repo, pullRequestNumber)
	if err != nil {
		return err
	}
	fmt.Printf("Merged pull request [%d].\n", pullRequestNumber)

	if opts.isKeepBranch {
		return nil
	}

	currentBranchName, errCurrentBranch := git.GetCurrentBranchName()
	if errCurrentBranch != nil {
		return errCurrentBranch
	}

	if currentBranchName == pr.Source.Branch.Name {
		_, errCheckout := git.Checkout(pr.Destination.Branch.Name)
		if errCheckout != nil {
			return errCheckout
		}
		fmt.Printf("Checked out to branch %s.", pr.Destination.Branch.Name)
	}

	_, errDelete := git.DeleteBranch(pr.Source.Branch.Name)
	if errDelete != nil {
		return errDelete
	}
	fmt.Printf("Deleted branch %s.", pr.Source.Branch.Name)

	return nil
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/hashicorp/vault/helper/kv-builder"
)

// WriteCommand is a Command that puts data into the Vault.
type WriteCommand struct {
	Meta

	// The fields below can be overwritten for tests
	testStdin io.Reader
}

func (c *WriteCommand) Run(args []string) int {
	var format string
	var force bool
	flags := c.Meta.FlagSet("write", FlagSetDefault)
	flags.StringVar(&format, "format", "table", "")
	flags.BoolVar(&force, "force", false, "")
	flags.BoolVar(&force, "f", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) < 2 && !force {
		c.Ui.Error("write expects at least two arguments")
		flags.Usage()
		return 1
	}

	path := args[0]
	if path[0] == '/' {
		path = path[1:]
	}

	data, err := c.parseData(args[1:])
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error loading data: %s", err))
		return 1
	}

	client, err := c.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error initializing client: %s", err))
		return 2
	}

	secret, err := client.Logical().Write(path, data)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error writing data to %s: %s", path, err))
		return 1
	}

	if secret == nil {
		c.Ui.Output(fmt.Sprintf("Success! Data written to: %s", path))
		return 0
	}

	return OutputSecret(c.Ui, format, secret)
}

func (c *WriteCommand) parseData(args []string) (map[string]interface{}, error) {
	var stdin io.Reader = os.Stdin
	if c.testStdin != nil {
		stdin = c.testStdin
	}

	builder := &kvbuilder.Builder{Stdin: stdin}
	if err := builder.Add(args...); err != nil {
		return nil, err
	}

	return builder.Map(), nil
}

func (c *WriteCommand) Synopsis() string {
	return "Write secrets or configuration into Vault"
}

func (c *WriteCommand) Help() string {
	helpText := `
Usage: vault write [options] path [data]

  Write data (secrets or configuration) into Vault.

  Write sends data into Vault at the given path. The behavior of the write
  is determined by the backend at the given path. For example, writing
  to "aws/policy/ops" will create an "ops" IAM policy for the AWS backend
  (configuration), but writing to "consul/foo" will write a value directly
  into Consul at that key. Check the documentation of the logical backend
  you're using for more information on key structure.

  Data is sent via additional arguments in "key=value" pairs. If value
  begins with an "@", then it is loaded from a file. If you want to start
  the value with a literal "@", then prefix the "@" with a slash: "\@".

General Options:

  ` + generalOptionsUsage() + `

Write Options:

  -f | -force             Force the write to continue without any data values
                          specified. This allows writing to keys that do not
                          need or expect any fields to be specified.

`
	return strings.TrimSpace(helpText)
}
<commit_msg>When writing from a file it must be a JSON file<commit_after>package command

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/hashicorp/vault/helper/kv-builder"
)

// WriteCommand is a Command that puts data into the Vault.
type WriteCommand struct {
	Meta

	// The fields below can be overwritten for tests
	testStdin io.Reader
}

func (c *WriteCommand) Run(args []string) int {
	var format string
	var force bool
	flags := c.Meta.FlagSet("write", FlagSetDefault)
	flags.StringVar(&format, "format", "table", "")
	flags.BoolVar(&force, "force", false, "")
	flags.BoolVar(&force, "f", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) < 2 && !force {
		c.Ui.Error("write expects at least two arguments")
		flags.Usage()
		return 1
	}

	path := args[0]
	if path[0] == '/' {
		path = path[1:]
	}

	data, err := c.parseData(args[1:])
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error loading data: %s", err))
		return 1
	}

	client, err := c.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error initializing client: %s", err))
		return 2
	}

	secret, err := client.Logical().Write(path, data)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error writing data to %s: %s", path, err))
		return 1
	}

	if secret == nil {
		c.Ui.Output(fmt.Sprintf("Success! Data written to: %s", path))
		return 0
	}

	return OutputSecret(c.Ui, format, secret)
}

func (c *WriteCommand) parseData(args []string) (map[string]interface{}, error) {
	var stdin io.Reader = os.Stdin
	if c.testStdin != nil {
		stdin = c.testStdin
	}

	builder := &kvbuilder.Builder{Stdin: stdin}
	if err := builder.Add(args...); err != nil {
		return nil, err
	}

	return builder.Map(), nil
}

func (c *WriteCommand) Synopsis() string {
	return "Write secrets or configuration into Vault"
}

func (c *WriteCommand) Help() string {
	helpText := `
Usage: vault write [options] path [data]

  Write data (secrets or configuration) into Vault.

  Write sends data into Vault at the given path. The behavior of the write
  is determined by the backend at the given path. For example, writing
  to "aws/policy/ops" will create an "ops" IAM policy for the AWS backend
  (configuration), but writing to "consul/foo" will write a value directly
  into Consul at that key. Check the documentation of the logical backend
  you're using for more information on key structure.

  Data is sent via additional arguments in "key=value" pairs. If value
  begins with an "@", then it is loaded from a JSON file. If you want to start
  the value with a literal "@", then prefix the "@" with a slash: "\@".

General Options:

  ` + generalOptionsUsage() + `

Write Options:

  -f | -force             Force the write to continue without any data values
                          specified. This allows writing to keys that do not
                          need or expect any fields to be specified.

`
	return strings.TrimSpace(helpText)
}
<|endoftext|>


<commit_before>package commands

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/codegangsta/cli"
	"github.com/docker/docker/pkg/fileutils"

	"github.com/yuuki1/droot/archive"
	"github.com/yuuki1/droot/aws"
	"github.com/yuuki1/droot/log"
	"github.com/yuuki1/droot/osutil"
)

var CommandArgPull = "--dest DESTINATION_DIRECTORY --src S3_ENDPOINT [--user USER] [--grpup GROUP] [--mode MODE]"
var CommandPull = cli.Command{
	Name:   "pull",
	Usage:  "Pull an extracted docker image from s3",
	Action: fatalOnError(doPull),
	Flags: []cli.Flag{
		cli.StringFlag{Name: "dest, d", Usage: "Local filesystem path (ex. /var/containers/app)"},
		cli.StringFlag{Name: "src, s", Usage: "Amazon S3 endpoint (ex. s3://drootexample/app.tar.gz)"},
		cli.StringFlag{Name: "user, u", Usage: "User (ID or name) to set after extracting archive (required superuser)"},
		cli.StringFlag{Name: "group, g", Usage: "Group (ID or name) to set after extracting archive (required superuser)"},
		cli.StringFlag{Name: "mode, m", Usage: "Mode of deployment. 'rsync' or 'symlink'. default is 'rsync'"},
	},
}

func doPull(c *cli.Context) error {
	destDir := c.String("dest")
	srcURL := c.String("src")
	if destDir == "" || srcURL == "" {
		cli.ShowCommandHelp(c, "pull")
		return errors.New("--src and --dest option required ")
	}

	s3URL, err := url.Parse(srcURL)
	if err != nil {
		return err
	}
	if s3URL.Scheme != "s3" {
		return fmt.Errorf("Not s3 scheme %s", srcURL)
	}

	mode := c.String("mode")
	if mode == "" {
		mode = "rsync"
	}
	if mode != "rsync" && mode != "symlink" {
		return fmt.Errorf("Invalid mode %s. '--mode' must be 'rsync' or 'symlink'.", mode)
	}

	uid, gid := os.Getuid(), os.Getgid()
	if group := c.String("group"); group != "" {
		if gid, err = osutil.LookupGroup(group); err != nil {
			return fmt.Errorf("Failed to lookup group:", err)
		}
	}
	if user := c.String("user"); user != "" {
		if uid, err = osutil.LookupUser(user); err != nil {
			return fmt.Errorf("Failed to lookup user:", err)
		}
	}

	tmp, err := ioutil.TempFile(os.TempDir(), "droot_gzip")
	if err != nil {
		return fmt.Errorf("Failed to create temporary file: %s", err)
	}
	defer func(f *os.File) {
		f.Close()
		os.Remove(f.Name())
	}(tmp)

	log.Info("-->", "Downloading", s3URL, "to", tmp.Name())

	if _, err := aws.NewS3Client().Download(s3URL, tmp); err != nil {
		return fmt.Errorf("Failed to download file(%s) from s3: %s", srcURL, err)
	}

	rawDir, err := ioutil.TempDir(os.TempDir(), "droot_raw")
	if err != nil {
		return fmt.Errorf("Failed to create temporary dir: %s", err)
	}
	defer os.RemoveAll(rawDir)

	log.Info("-->", "Extracting archive", tmp.Name(), "to", rawDir)

	if err := archive.ExtractTarGz(tmp, rawDir, uid, gid); err != nil {
		return fmt.Errorf("Failed to extract archive: %s", err)
	}

	if mode == "rsync" {
		log.Info("-->", "Syncing", "from", rawDir, "to", destDir)

		if err := archive.Rsync(rawDir, destDir); err != nil {
			return fmt.Errorf("Failed to rsync: %s", err)
		}
	} else if mode == "symlink" {
		mainLink := destDir + ".drootmain"
		backupLink := destDir + ".drootbackup"
		mainDir := destDir + ".d/main"
		backupDir := destDir + ".d/backup"

		for _, dir := range []string{mainDir, backupDir} {
			if err := fileutils.CreateIfNotExists(dir, true); err != nil { // mkdir -p
				return fmt.Errorf("Failed to create directory %s: %s", dir, err)
			}
		}

		// Return error if the working directory that droot internally uses exists
		for _, link := range []string{mainLink, backupLink, destDir} {
			if !osutil.IsSymlink(link) && (osutil.ExistsFile(link) || osutil.ExistsDir(link)) {
				return fmt.Errorf("%s already exists. Please use another directory as --dest option or delete %s", link)
			}
		}

		if err := osutil.Symlink(mainDir, mainLink); err != nil {
			return fmt.Errorf("Failed to create symlink %s: %s", mainLink, err)
		}
		if err := osutil.Symlink(backupDir, backupLink); err != nil {
			return fmt.Errorf("Failed to create symlink %s: %s", backupLink, err)
		}

		// Atomic deploy by symlink
		// 1. rsync maindir => backupdir
		// 2. mv -T backuplink destdir
		// 3. rsync rawdir => maindir
		// 4. mv -T mainlink destdir

		log.Info("-->", "Syncing", "from", mainDir, "to", backupDir)
		if err := archive.Rsync(mainDir, backupDir); err != nil {
			return fmt.Errorf("Failed to rsync: %s", err)
		}
		log.Info("-->", "Renaming", "from", backupLink, "to", destDir)
		if err := os.Rename(backupLink, destDir); err != nil {
			return fmt.Errorf("Failed to rename %s: %s", destDir, err)
		}
		log.Info("-->", "Syncing", "from", rawDir, "to", mainDir)
		if err := archive.Rsync(rawDir, mainDir); err != nil {
			return fmt.Errorf("Failed to rsync: %s", err)
		}
		log.Info("-->", "Renaming", "from", mainLink, "to", destDir)
		if err := os.Rename(mainLink, destDir); err != nil {
			return fmt.Errorf("Failed to rename %s: %s", destDir, err)
		}
	} else {
		return fmt.Errorf("Unreachable code. invalid mode %s", mode)
	}

	if err := os.Lchown(destDir, uid, gid); err != nil {
		return fmt.Errorf("Failed to chown %d:%d: %s", uid, gid, err)
	}
	if err := os.Chmod(destDir, os.FileMode(0755)); err != nil {
		return fmt.Errorf("Failed to chmod %s: %s", destDir, err)
	}

	return nil
}
<commit_msg>Move the part of symlink deploy to deployWithSymlink()<commit_after>package commands

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/codegangsta/cli"
	"github.com/docker/docker/pkg/fileutils"

	"github.com/yuuki1/droot/archive"
	"github.com/yuuki1/droot/aws"
	"github.com/yuuki1/droot/log"
	"github.com/yuuki1/droot/osutil"
)

var CommandArgPull = "--dest DESTINATION_DIRECTORY --src S3_ENDPOINT [--user USER] [--grpup GROUP] [--mode MODE]"
var CommandPull = cli.Command{
	Name:   "pull",
	Usage:  "Pull an extracted docker image from s3",
	Action: fatalOnError(doPull),
	Flags: []cli.Flag{
		cli.StringFlag{Name: "dest, d", Usage: "Local filesystem path (ex. /var/containers/app)"},
		cli.StringFlag{Name: "src, s", Usage: "Amazon S3 endpoint (ex. s3://drootexample/app.tar.gz)"},
		cli.StringFlag{Name: "user, u", Usage: "User (ID or name) to set after extracting archive (required superuser)"},
		cli.StringFlag{Name: "group, g", Usage: "Group (ID or name) to set after extracting archive (required superuser)"},
		cli.StringFlag{Name: "mode, m", Usage: "Mode of deployment. 'rsync' or 'symlink'. default is 'rsync'"},
	},
}

func doPull(c *cli.Context) error {
	destDir := c.String("dest")
	srcURL := c.String("src")
	if destDir == "" || srcURL == "" {
		cli.ShowCommandHelp(c, "pull")
		return errors.New("--src and --dest option required ")
	}

	s3URL, err := url.Parse(srcURL)
	if err != nil {
		return err
	}
	if s3URL.Scheme != "s3" {
		return fmt.Errorf("Not s3 scheme %s", srcURL)
	}

	mode := c.String("mode")
	if mode == "" {
		mode = "rsync"
	}
	if mode != "rsync" && mode != "symlink" {
		return fmt.Errorf("Invalid mode %s. '--mode' must be 'rsync' or 'symlink'.", mode)
	}

	uid, gid := os.Getuid(), os.Getgid()
	if group := c.String("group"); group != "" {
		if gid, err = osutil.LookupGroup(group); err != nil {
			return fmt.Errorf("Failed to lookup group:", err)
		}
	}
	if user := c.String("user"); user != "" {
		if uid, err = osutil.LookupUser(user); err != nil {
			return fmt.Errorf("Failed to lookup user:", err)
		}
	}

	tmp, err := ioutil.TempFile(os.TempDir(), "droot_gzip")
	if err != nil {
		return fmt.Errorf("Failed to create temporary file: %s", err)
	}
	defer func(f *os.File) {
		f.Close()
		os.Remove(f.Name())
	}(tmp)

	log.Info("-->", "Downloading", s3URL, "to", tmp.Name())

	if _, err := aws.NewS3Client().Download(s3URL, tmp); err != nil {
		return fmt.Errorf("Failed to download file(%s) from s3: %s", srcURL, err)
	}

	rawDir, err := ioutil.TempDir(os.TempDir(), "droot_raw")
	if err != nil {
		return fmt.Errorf("Failed to create temporary dir: %s", err)
	}
	defer os.RemoveAll(rawDir)

	log.Info("-->", "Extracting archive", tmp.Name(), "to", rawDir)

	if err := archive.ExtractTarGz(tmp, rawDir, uid, gid); err != nil {
		return fmt.Errorf("Failed to extract archive: %s", err)
	}

	if mode == "rsync" {
		log.Info("-->", "Syncing", "from", rawDir, "to", destDir)

		if err := archive.Rsync(rawDir, destDir); err != nil {
			return fmt.Errorf("Failed to rsync: %s", err)
		}
	} else if mode == "symlink" {
		if err := deployWithSymlink(rawDir, destDir); err != nil {
			return err
		}
	} else {
		return fmt.Errorf("Unreachable code. invalid mode %s", mode)
	}

	if err := os.Lchown(destDir, uid, gid); err != nil {
		return fmt.Errorf("Failed to chown %d:%d: %s", uid, gid, err)
	}
	if err := os.Chmod(destDir, os.FileMode(0755)); err != nil {
		return fmt.Errorf("Failed to chmod %s: %s", destDir, err)
	}

	return nil
}

// Atomic deploy by symlink
// 1. rsync maindir => backupdir
// 2. mv -T backuplink destdir
// 3. rsync srcdir => maindir
// 4. mv -T mainlink destdir
func deployWithSymlink(srcDir, destDir string) error {
	mainLink := destDir + ".drootmain"
	backupLink := destDir + ".drootbackup"
	mainDir := destDir + ".d/main"
	backupDir := destDir + ".d/backup"

	for _, dir := range []string{mainDir, backupDir} {
		if err := fileutils.CreateIfNotExists(dir, true); err != nil { // mkdir -p
			return fmt.Errorf("Failed to create directory %s: %s", dir, err)
		}
	}

	// Return error if the working directory that droot internally uses exists
	for _, link := range []string{mainLink, backupLink, destDir} {
		if !osutil.IsSymlink(link) && (osutil.ExistsFile(link) || osutil.ExistsDir(link)) {
			return fmt.Errorf("%s already exists. Please use another directory as --dest option or delete %s", link)
		}
	}

	if err := osutil.Symlink(mainDir, mainLink); err != nil {
		return fmt.Errorf("Failed to create symlink %s: %s", mainLink, err)
	}
	if err := osutil.Symlink(backupDir, backupLink); err != nil {
		return fmt.Errorf("Failed to create symlink %s: %s", backupLink, err)
	}

	log.Info("-->", "Syncing", "from", mainDir, "to", backupDir)
	if err := archive.Rsync(mainDir, backupDir); err != nil {
		return fmt.Errorf("Failed to rsync: %s", err)
	}

	log.Info("-->", "Renaming", "from", backupLink, "to", destDir)
	if err := os.Rename(backupLink, destDir); err != nil {
		return fmt.Errorf("Failed to rename %s: %s", destDir, err)
	}

	log.Info("-->", "Syncing", "from", srcDir, "to", mainDir)
	if err := archive.Rsync(srcDir, mainDir); err != nil {
		return fmt.Errorf("Failed to rsync: %s", err)
	}

	log.Info("-->", "Renaming", "from", mainLink, "to", destDir)
	if err := os.Rename(mainLink, destDir); err != nil {
		return fmt.Errorf("Failed to rename %s: %s", destDir, err)
	}

	return nil
}

<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/currantlabs/ble"
	"github.com/currantlabs/ble/examples/lib/gatt"
)

var (
	name = flag.String("name", "Gopher", "name of remote peripheral")
	addr = flag.String("addr", "", "address of remote peripheral (MAC on Linux, UUID on OS X)")
	sub  = flag.Duration("sub", 0, "subscribe to notification and indication for a specified period")
)

// matcher returns true if the advertisement matches our search criteria.
type matcher func(a ble.Advertisement) bool

// explorer connects to a remote peripheral and explores its GATT server.
type explorerer struct {
	match matcher
	ch    chan ble.Advertisement
}

func (e *explorerer) Handle(a ble.Advertisement) {
	if e.match(a) {
		gatt.StopScanning()
		e.ch <- a
	}
}

func explorer(cln ble.Client) error {
	fmt.Printf("Exploring Peripheral [ %s ] ...\n", cln.Address())

	ss, err := cln.DiscoverServices(nil)
	if err != nil {
		return fmt.Errorf("can't discover services: %s\n", err)
	}
	for _, s := range ss {
		fmt.Printf("Service: %s %s\n", s.UUID.String(), ble.Name(s.UUID))

		cs, err := cln.DiscoverCharacteristics(nil, s)
		if err != nil {
			return fmt.Errorf("can't discover characteristics: %s\n", err)
		}
		for _, c := range cs {
			fmt.Printf("  Characteristic: %s, Property: 0x%02X (%s), %s\n", c.UUID, c.Property, propString(c.Property), ble.Name(c.UUID))
			if (c.Property & ble.CharRead) != 0 {
				b, err := cln.ReadCharacteristic(c)
				if err != nil {
					fmt.Printf("Failed to read characteristic: %s\n", err)
					continue
				}
				fmt.Printf("    Value         %x | %q\n", b, b)
			}

			ds, err := cln.DiscoverDescriptors(nil, c)
			if err != nil {
				return fmt.Errorf("can't discover descriptors: %s\n", err)
			}
			for _, d := range ds {
				fmt.Printf("    Descriptor: %s, %s\n", d.UUID, ble.Name(d.UUID))
				b, err := cln.ReadDescriptor(d)
				if err != nil {
					fmt.Printf("Failed to read descriptor: %s\n", err)
					continue
				}
				fmt.Printf("    Value         %x | %q\n", b, b)
			}
			if *sub != 0 {
				// Don't bother to subscribe the Service Changed characteristics.
				if c.UUID.Equal(ble.ServiceChangedUUID) {
					continue
				}

				// Don't touch the Apple-specific Service/Characteristic.
				// Service: D0611E78BBB44591A5F8487910AE4366
				// Characteristic: 8667556C9A374C9184ED54EE27D90049, Property: 0x18 (WN),
				//   Descriptor: 2902, Client Characteristic Configuration
				//   Value         0000 | "\x00\x00"
				if c.UUID.Equal(ble.MustParse("8667556C9A374C9184ED54EE27D90049")) {
					continue
				}

				if (c.Property & ble.CharNotify) != 0 {
					fmt.Printf("\n-- Subscribe to notification for %s --\n", *sub)
					h := func(req []byte) { fmt.Printf("Notified: %q [ % X ]\n", string(req), req) }
					if err := cln.Subscribe(c, false, h); err != nil {
						log.Fatalf("subscribe failed: %s", err)
					}
					time.Sleep(*sub)
					if err := cln.Unsubscribe(c, false); err != nil {
						log.Fatalf("unsubscribe failed: %s", err)
					}
					fmt.Printf("-- Unsubscribe to notification --\n")
				}
				if (c.Property & ble.CharIndicate) != 0 {
					fmt.Printf("\n-- Subscribe to indication of %s --\n", *sub)
					h := func(req []byte) { fmt.Printf("Indicated: %q [ % X ]\n", string(req), req) }
					if err := cln.Subscribe(c, true, h); err != nil {
						log.Fatalf("subscribe failed: %s", err)
					}
					time.Sleep(*sub)
					if err := cln.Unsubscribe(c, true); err != nil {
						log.Fatalf("unsubscribe failed: %s", err)
					}
					fmt.Printf("-- Unsubscribe to indication --\n")
				}
			}

		}
		fmt.Printf("\n")
	}
	return nil
}

func propString(p ble.Property) string {
	var s string
	for k, v := range map[ble.Property]string{
		ble.CharBroadcast:   "B",
		ble.CharRead:        "R",
		ble.CharWriteNR:     "w",
		ble.CharWrite:       "W",
		ble.CharNotify:      "N",
		ble.CharIndicate:    "I",
		ble.CharSignedWrite: "S",
		ble.CharExtended:    "E",
	} {
		if p&k != 0 {
			s += v
		}
	}
	return s
}

func main() {
	flag.Parse()

	// Default to search device with name of Gopher (or specified by user).
	match := func(a ble.Advertisement) bool {
		return strings.ToUpper(a.LocalName()) == strings.ToUpper(*name)
	}

	// If addr is specified, search for addr instead.
	if len(*addr) != 0 {
		match = func(a ble.Advertisement) bool {
			return strings.ToUpper(a.Address().String()) == strings.ToUpper(*addr)
		}
	}

	exp := &explorerer{
		ch:    make(chan ble.Advertisement),
		match: match,
	}

	if err := gatt.SetAdvHandler(exp); err != nil {
		log.Fatalf("can't set adv handler: %s", err)
	}

	if err := gatt.Scan(false); err != nil {
		log.Fatalf("can't scan: %s", err)
	}

	// Wait for the exploration is done.
	a := <-exp.ch

	// Dial connects to the remote device.
	cln, err := gatt.Dial(a.Address())
	if err != nil {
		log.Fatalf("can't dial: %s", err)
	}

	// Start the exploration.
	explorer(cln)

	// Disconnect the connection. (On OS X, this might take a while.)
	fmt.Printf("Disconnecting [ %s ]... (this might take up to few seconds on OS X)\n", cln.Address())
	cln.CancelConnection()
}
<commit_msg>example: show handles in explorer<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/currantlabs/ble"
	"github.com/currantlabs/ble/examples/lib/gatt"
)

var (
	name = flag.String("name", "Gopher", "name of remote peripheral")
	addr = flag.String("addr", "", "address of remote peripheral (MAC on Linux, UUID on OS X)")
	sub  = flag.Duration("sub", 0, "subscribe to notification and indication for a specified period")
)

// matcher returns true if the advertisement matches our search criteria.
type matcher func(a ble.Advertisement) bool

// explorer connects to a remote peripheral and explores its GATT server.
type explorerer struct {
	match matcher
	ch    chan ble.Advertisement
}

func (e *explorerer) Handle(a ble.Advertisement) {
	if e.match(a) {
		gatt.StopScanning()
		e.ch <- a
	}
}

func explorer(cln ble.Client) error {
	fmt.Printf("Exploring Peripheral [ %s ] ...\n", cln.Address())

	ss, err := cln.DiscoverServices(nil)
	if err != nil {
		return fmt.Errorf("can't discover services: %s\n", err)
	}
	for _, s := range ss {
		fmt.Printf("Service: %s %s, Handle (0x%02X)\n", s.UUID.String(), ble.Name(s.UUID), s.Handle)

		cs, err := cln.DiscoverCharacteristics(nil, s)
		if err != nil {
			return fmt.Errorf("can't discover characteristics: %s\n", err)
		}
		for _, c := range cs {
			fmt.Printf("  Characteristic: %s, Property: 0x%02X (%s), %s, Handle(0x%02X), VHandle(0x%02X)\n",
				c.UUID, c.Property, propString(c.Property), ble.Name(c.UUID), c.Handle, c.ValueHandle)
			if (c.Property & ble.CharRead) != 0 {
				b, err := cln.ReadCharacteristic(c)
				if err != nil {
					fmt.Printf("Failed to read characteristic: %s\n", err)
					continue
				}
				fmt.Printf("    Value         %x | %q\n", b, b)
			}

			ds, err := cln.DiscoverDescriptors(nil, c)
			if err != nil {
				return fmt.Errorf("can't discover descriptors: %s\n", err)
			}
			for _, d := range ds {
				fmt.Printf("    Descriptor: %s, %s, Handle(0x%02x)\n", d.UUID, ble.Name(d.UUID), d.Handle)
				b, err := cln.ReadDescriptor(d)
				if err != nil {
					fmt.Printf("Failed to read descriptor: %s\n", err)
					continue
				}
				fmt.Printf("    Value         %x | %q\n", b, b)
			}
			if *sub != 0 {
				// Don't bother to subscribe the Service Changed characteristics.
				if c.UUID.Equal(ble.ServiceChangedUUID) {
					continue
				}

				// Don't touch the Apple-specific Service/Characteristic.
				// Service: D0611E78BBB44591A5F8487910AE4366
				// Characteristic: 8667556C9A374C9184ED54EE27D90049, Property: 0x18 (WN),
				//   Descriptor: 2902, Client Characteristic Configuration
				//   Value         0000 | "\x00\x00"
				if c.UUID.Equal(ble.MustParse("8667556C9A374C9184ED54EE27D90049")) {
					continue
				}

				if (c.Property & ble.CharNotify) != 0 {
					fmt.Printf("\n-- Subscribe to notification for %s --\n", *sub)
					h := func(req []byte) { fmt.Printf("Notified: %q [ % X ]\n", string(req), req) }
					if err := cln.Subscribe(c, false, h); err != nil {
						log.Fatalf("subscribe failed: %s", err)
					}
					time.Sleep(*sub)
					if err := cln.Unsubscribe(c, false); err != nil {
						log.Fatalf("unsubscribe failed: %s", err)
					}
					fmt.Printf("-- Unsubscribe to notification --\n")
				}
				if (c.Property & ble.CharIndicate) != 0 {
					fmt.Printf("\n-- Subscribe to indication of %s --\n", *sub)
					h := func(req []byte) { fmt.Printf("Indicated: %q [ % X ]\n", string(req), req) }
					if err := cln.Subscribe(c, true, h); err != nil {
						log.Fatalf("subscribe failed: %s", err)
					}
					time.Sleep(*sub)
					if err := cln.Unsubscribe(c, true); err != nil {
						log.Fatalf("unsubscribe failed: %s", err)
					}
					fmt.Printf("-- Unsubscribe to indication --\n")
				}
			}

		}
		fmt.Printf("\n")
	}
	return nil
}

func propString(p ble.Property) string {
	var s string
	for k, v := range map[ble.Property]string{
		ble.CharBroadcast:   "B",
		ble.CharRead:        "R",
		ble.CharWriteNR:     "w",
		ble.CharWrite:       "W",
		ble.CharNotify:      "N",
		ble.CharIndicate:    "I",
		ble.CharSignedWrite: "S",
		ble.CharExtended:    "E",
	} {
		if p&k != 0 {
			s += v
		}
	}
	return s
}

func main() {
	flag.Parse()

	// Default to search device with name of Gopher (or specified by user).
	match := func(a ble.Advertisement) bool {
		return strings.ToUpper(a.LocalName()) == strings.ToUpper(*name)
	}

	// If addr is specified, search for addr instead.
	if len(*addr) != 0 {
		match = func(a ble.Advertisement) bool {
			return strings.ToUpper(a.Address().String()) == strings.ToUpper(*addr)
		}
	}

	exp := &explorerer{
		ch:    make(chan ble.Advertisement),
		match: match,
	}

	if err := gatt.SetAdvHandler(exp); err != nil {
		log.Fatalf("can't set adv handler: %s", err)
	}

	if err := gatt.Scan(false); err != nil {
		log.Fatalf("can't scan: %s", err)
	}

	// Wait for the exploration is done.
	a := <-exp.ch

	// Dial connects to the remote device.
	cln, err := gatt.Dial(a.Address())
	if err != nil {
		log.Fatalf("can't dial: %s", err)
	}

	// Start the exploration.
	explorer(cln)

	// Disconnect the connection. (On OS X, this might take a while.)
	fmt.Printf("Disconnecting [ %s ]... (this might take up to few seconds on OS X)\n", cln.Address())
	cln.CancelConnection()
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"os"
	"path"
	"regexp"
	"strconv"
)

//Regex to remove tabs and newlines (const)
var tabsNewlines = regexp.MustCompile(`\n(\t)?`)

//SyslogHeader gathers environment information to generate a log prefix
func SyslogHeader() string {
	//Fetch process name, pid and hostname
	processName := path.Base(os.Args[0])
	pid := strconv.Itoa(os.Getpid())
	hostname, err := os.Hostname()

	if err != nil {
		//This is a non-fatal error and hence we just print a message
		fmt.Printf("rlog initialization error: could not fetch machine hostname")
	}

	//Generate a prefix out of this information
	prefix := hostname + " " + processName + "[" + pid + "]: "

	return prefix
}

//FormatMessage generates a log message
func FormatMessage(rawRlogMsg *RlogMsg, prefix string, removeNewlines bool) string {
	logMsg := rawRlogMsg.Msg
	trace := rawRlogMsg.StackTrace
	if removeNewlines {
		//Replace newlines by #012 and remove indentations
		logMsg = ReplaceNewlines(logMsg)
	}

	//Print the log message and stack trace if appropriate
	res := rawRlogMsg.Timestamp + " " + prefix + logMsg
	if trace != "" {
		if removeNewlines {
			trace = ReplaceNewlines(trace)
			res += ", trace: " + trace
		} else {
			res += "\n" + trace
		}
	}

	return res
}

//ReplaceNewlines replaces newlines with #012 and removes indentations
//Arguments: a string for newline replacement
//Returns: string with #012 instead of newlines
func ReplaceNewlines(msg string) string {
	return tabsNewlines.ReplaceAllString(msg, "#012")
}
<commit_msg>acu171605 use spaces for substitution instead of #012 for prettier logging of newlines and tabs<commit_after>package common

import (
	"fmt"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

// Regex to remove tabs and newlines.
const (
  replacementWhitespacePattern = `[\r\n\t]+`
  replacementWhitespace        = "  "
)

var replaceWhitespaceRegex = regexp.MustCompile(replacementWhitespacePattern)

//SyslogHeader gathers environment information to generate a log prefix
func SyslogHeader() string {
	//Fetch process name, pid and hostname
	processName := path.Base(os.Args[0])
	pid := strconv.Itoa(os.Getpid())
	hostname, err := os.Hostname()

	if err != nil {
		//This is a non-fatal error and hence we just print a message
		fmt.Printf("rlog initialization error: could not fetch machine hostname")
	}

	//Generate a prefix out of this information
	prefix := hostname + " " + processName + "[" + pid + "]: "

	return prefix
}

//FormatMessage generates a log message
func FormatMessage(rawRlogMsg *RlogMsg, prefix string, removeNewlines bool) string {
	logMsg := rawRlogMsg.Msg
	trace := rawRlogMsg.StackTrace
	if removeNewlines {
		//Replace whitespace
		logMsg = ReplaceNewlines(logMsg)
	}

	//Print the log message and stack trace if appropriate
	res := rawRlogMsg.Timestamp + " " + prefix + logMsg
	if trace != "" {
		if removeNewlines {
			trace = ReplaceNewlines(trace)
			res += ", trace: " + trace
		} else {
			res += "\n" + trace
		}
	}

	return res
}

//ReplaceNewlines any tabs/newlines with double-space and removes indentations
//Arguments: a string for newline replacement
//Returns: string with #012 instead of newlines
func ReplaceNewlines(msg string) string {
	return strings.Trim(
		replaceWhitespaceRegex.ReplaceAllString(msg, replacementWhitespace), " ")
}
<|endoftext|>


<commit_before>// Copyright 2020 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package infosync

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path"
	"reflect"
	"runtime"
	"testing"
	"time"

	. "github.com/pingcap/check"
	"github.com/pingcap/failpoint"
	"github.com/pingcap/tidb/ddl/util"
	"github.com/pingcap/tidb/owner"
	"go.etcd.io/etcd/integration"
)

func (is *InfoSyncer) getTopologyFromEtcd(ctx context.Context) (*topologyInfo, error) {
	key := fmt.Sprintf("%s/%s:%v/info", TopologyInformationPath, is.info.IP, is.info.Port)
	resp, err := is.etcdCli.Get(ctx, key)
	if err != nil {
		return nil, err
	}
	if len(resp.Kvs) == 0 {
		return nil, errors.New("not-exists")
	}
	if len(resp.Kvs) != 1 {
		return nil, errors.New("resp.Kvs error")
	}
	var ret topologyInfo
	err = json.Unmarshal(resp.Kvs[0].Value, &ret)
	if err != nil {
		return nil, err
	}
	return &ret, nil
}

func (is *InfoSyncer) ttlKeyExists(ctx context.Context) (bool, error) {
	key := fmt.Sprintf("%s/%s:%v/ttl", TopologyInformationPath, is.info.IP, is.info.Port)
	resp, err := is.etcdCli.Get(ctx, key)
	if err != nil {
		return false, err
	}
	if len(resp.Kvs) >= 2 {
		return false, errors.New("too many arguments in resp.Kvs")
	}
	return len(resp.Kvs) == 1, nil
}

func TestT(t *testing.T) {
	CustomVerboseFlag = true
	TestingT(t)
}

var _ = Suite(&testSuite{})

type testSuite struct {
}

func TestTopology(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows")
	}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	currentID := "test"

	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1})
	defer clus.Terminate(t)

	cli := clus.RandClient()

	err := failpoint.Enable("github.com/pingcap/tidb/domain/infosync/mockServerInfo", "return(true)")
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		err := failpoint.Disable("github.com/pingcap/tidb/domain/infosync/mockServerInfo")
		if err != nil {
			t.Fatal(err)
		}
	}()

	info, err := GlobalInfoSyncerInit(ctx, currentID, func() uint64 { return 1 }, cli, false)
	if err != nil {
		t.Fatal(err)
	}

	err = info.newTopologySessionAndStoreServerInfo(ctx, owner.NewSessionDefaultRetryCnt)

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

	topo, err := info.getTopologyFromEtcd(ctx)
	if err != nil {
		t.Fatal(err)
	}

	if topo.StartTimestamp != 1282967700000 {
		t.Fatal("start_timestamp of topology info does not match")
	}
	if v, ok := topo.Labels["foo"]; !ok || v != "bar" {
		t.Fatal("labels of topology info does not match")
	}

	if !reflect.DeepEqual(*topo, info.getTopologyInfo()) {
		t.Fatal("the info in etcd is not match with info.")
	}

	nonTTLKey := fmt.Sprintf("%s/%s:%v/info", TopologyInformationPath, info.info.IP, info.info.Port)
	ttlKey := fmt.Sprintf("%s/%s:%v/ttl", TopologyInformationPath, info.info.IP, info.info.Port)

	err = util.DeleteKeyFromEtcd(nonTTLKey, cli, owner.NewSessionDefaultRetryCnt, time.Second)
	if err != nil {
		t.Fatal(err)
	}

	// Refresh and re-test if the key exists
	err = info.RestartTopology(ctx)
	if err != nil {
		t.Fatal(err)
	}

	topo, err = info.getTopologyFromEtcd(ctx)
	if err != nil {
		t.Fatal(err)
	}

	s, err := os.Executable()
	if err != nil {
		t.Fatal(err)
	}

	dir := path.Dir(s)

	if topo.DeployPath != dir {
		t.Fatal("DeployPath not match expected path")
	}

	if topo.StartTimestamp != 1282967700000 {
		t.Fatal("start_timestamp of topology info does not match")
	}

	if !reflect.DeepEqual(*topo, info.getTopologyInfo()) {
		t.Fatal("the info in etcd is not match with info.")
	}

	// check ttl key
	ttlExists, err := info.ttlKeyExists(ctx)
	if err != nil {
		t.Fatal(err)
	}
	if !ttlExists {
		t.Fatal("ttl non-exists")
	}

	err = util.DeleteKeyFromEtcd(ttlKey, cli, owner.NewSessionDefaultRetryCnt, time.Second)
	if err != nil {
		t.Fatal(err)
	}
	err = info.updateTopologyAliveness(ctx)
	if err != nil {
		t.Fatal(err)
	}

	ttlExists, err = info.ttlKeyExists(ctx)
	if err != nil {
		t.Fatal(err)
	}
	if !ttlExists {
		t.Fatal("ttl non-exists")
	}
}
<commit_msg>domain/infosync: migrate test-infra to testify (#26288)<commit_after>// Copyright 2020 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package infosync

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path"
	"runtime"
	"testing"
	"time"

	"github.com/pingcap/failpoint"
	"github.com/pingcap/tidb/ddl/util"
	"github.com/pingcap/tidb/owner"
	"github.com/pingcap/tidb/util/testbridge"
	"github.com/stretchr/testify/require"
	"go.etcd.io/etcd/integration"
	"go.uber.org/goleak"
)

func TestMain(m *testing.M) {
	testbridge.WorkaroundGoCheckFlags()
	opts := []goleak.Option{
		goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"),
	}
	goleak.VerifyTestMain(m, opts...)
}

func TestTopology(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows")
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	currentID := "test"

	cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1})
	defer cluster.Terminate(t)

	client := cluster.RandClient()

	require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/infosync/mockServerInfo", "return(true)"))
	defer func() {
		err := failpoint.Disable("github.com/pingcap/tidb/domain/infosync/mockServerInfo")
		require.NoError(t, err)
	}()

	info, err := GlobalInfoSyncerInit(ctx, currentID, func() uint64 { return 1 }, client, false)
	require.NoError(t, err)

	err = info.newTopologySessionAndStoreServerInfo(ctx, owner.NewSessionDefaultRetryCnt)
	require.NoError(t, err)

	topology, err := info.getTopologyFromEtcd(ctx)
	require.NoError(t, err)
	require.Equal(t, int64(1282967700000), topology.StartTimestamp)

	v, ok := topology.Labels["foo"]
	require.True(t, ok)
	require.Equal(t, "bar", v)
	require.Equal(t, info.getTopologyInfo(), *topology)

	nonTTLKey := fmt.Sprintf("%s/%s:%v/info", TopologyInformationPath, info.info.IP, info.info.Port)
	ttlKey := fmt.Sprintf("%s/%s:%v/ttl", TopologyInformationPath, info.info.IP, info.info.Port)

	err = util.DeleteKeyFromEtcd(nonTTLKey, client, owner.NewSessionDefaultRetryCnt, time.Second)
	require.NoError(t, err)

	// Refresh and re-test if the key exists
	err = info.RestartTopology(ctx)
	require.NoError(t, err)

	topology, err = info.getTopologyFromEtcd(ctx)
	require.NoError(t, err)

	s, err := os.Executable()
	require.NoError(t, err)

	dir := path.Dir(s)
	require.Equal(t, dir, topology.DeployPath)
	require.Equal(t, int64(1282967700000), topology.StartTimestamp)
	require.Equal(t, info.getTopologyInfo(), *topology)

	// check ttl key
	ttlExists, err := info.ttlKeyExists(ctx)
	require.NoError(t, err)
	require.True(t, ttlExists)

	err = util.DeleteKeyFromEtcd(ttlKey, client, owner.NewSessionDefaultRetryCnt, time.Second)
	require.NoError(t, err)

	err = info.updateTopologyAliveness(ctx)
	require.NoError(t, err)

	ttlExists, err = info.ttlKeyExists(ctx)
	require.NoError(t, err)
	require.True(t, ttlExists)
}

func (is *InfoSyncer) getTopologyFromEtcd(ctx context.Context) (*topologyInfo, error) {
	key := fmt.Sprintf("%s/%s:%v/info", TopologyInformationPath, is.info.IP, is.info.Port)
	resp, err := is.etcdCli.Get(ctx, key)
	if err != nil {
		return nil, err
	}
	if len(resp.Kvs) == 0 {
		return nil, errors.New("not-exists")
	}
	if len(resp.Kvs) != 1 {
		return nil, errors.New("resp.Kvs error")
	}
	var ret topologyInfo
	err = json.Unmarshal(resp.Kvs[0].Value, &ret)
	if err != nil {
		return nil, err
	}
	return &ret, nil
}

func (is *InfoSyncer) ttlKeyExists(ctx context.Context) (bool, error) {
	key := fmt.Sprintf("%s/%s:%v/ttl", TopologyInformationPath, is.info.IP, is.info.Port)
	resp, err := is.etcdCli.Get(ctx, key)
	if err != nil {
		return false, err
	}
	if len(resp.Kvs) >= 2 {
		return false, errors.New("too many arguments in resp.Kvs")
	}
	return len(resp.Kvs) == 1, nil
}
<|endoftext|>


<commit_before>package taskevents

import (
	"fmt"
	"strings"
	"time"

	"github.com/hashicorp/nomad/api"
	"github.com/hashicorp/nomad/e2e/framework"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"

	"github.com/hashicorp/nomad/e2e/e2eutil"
	"github.com/hashicorp/nomad/helper/uuid"
)

type TaskEventsTest struct {
	framework.TC
	jobIds []string
}

func init() {
	framework.AddSuites(&framework.TestSuite{
		Component:   "TaskEvents",
		CanRunLocal: true,
		Cases: []framework.TestCase{
			new(TaskEventsTest),
		},
	})
}

func (tc *TaskEventsTest) BeforeAll(f *framework.F) {
	e2eutil.WaitForLeader(f.T(), tc.Nomad())
	e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 1)
}

func (tc *TaskEventsTest) AfterEach(f *framework.F) {
	nomadClient := tc.Nomad()
	jobs := nomadClient.Jobs()
	// Stop all jobs in test
	for _, id := range tc.jobIds {
		jobs.Deregister(id, true, nil)
	}
	// Garbage collect
	nomadClient.System().GarbageCollect()
}

func formatEvents(events []*api.TaskEvent) string {
	estrs := make([]string, len(events))
	for i, e := range events {
		estrs[i] = fmt.Sprintf("%2d %-20s fail=%t msg=> %s", i, e.Type, e.FailsTask, e.DisplayMessage)
	}
	return strings.Join(estrs, "\n")
}

// waitUntilEvents submits a job and then waits until the expected number of
// events exist.
//
// The job name is used to load the job file from "input/${job}.nomad", and
// events are only inspected for tasks named the same as the job. That task's
// state is returned as well as the last allocation received.
func (tc *TaskEventsTest) waitUntilEvents(f *framework.F, jobName string, numEvents int) (*api.Allocation, *api.TaskState) {
	t := f.T()
	nomadClient := tc.Nomad()
	uuid := uuid.Generate()
	uniqJobId := jobName + uuid[0:8]
	tc.jobIds = append(tc.jobIds, uniqJobId)

	jobFile := fmt.Sprintf("taskevents/input/%s.nomad", jobName)
	allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, jobFile, uniqJobId, "")

	require.Len(t, allocs, 1)
	allocID := allocs[0].ID
	qo := &api.QueryOptions{
		WaitTime: time.Second,
	}

	// Capture state outside of wait to ease assertions once expected
	// number of events have been received.
	var alloc *api.Allocation
	var taskState *api.TaskState

	testutil.WaitForResultRetries(10, func() (bool, error) {
		a, meta, err := nomadClient.Allocations().Info(allocID, qo)
		if err != nil {
			return false, err
		}

		qo.WaitIndex = meta.LastIndex

		// Capture alloc and task state
		alloc = a
		taskState = a.TaskStates[jobName]
		if taskState == nil {
			return false, fmt.Errorf("task state not found for %s", jobName)
		}

		// Assert expected number of task events
		if len(taskState.Events) != numEvents {
			return false, fmt.Errorf("expected %d task events but found %d\n%s",
				numEvents, len(taskState.Events), formatEvents(taskState.Events),
			)
		}

		return true, nil
	}, func(err error) {
		t.Fatalf("task events error: %v", err)
	})

	return alloc, taskState
}

func (tc *TaskEventsTest) TestTaskEvents_SimpleBatch(f *framework.F) {
	t := f.T()
	_, taskState := tc.waitUntilEvents(f, "simple_batch", 4)
	events := taskState.Events

	// Assert task did not fail
	require.Falsef(t, taskState.Failed, "task unexpectedly failed after %d events\n%s",
		len(events), formatEvents(events),
	)

	// Assert the expected type of events were emitted in a specific order
	// (based on v0.8.6)
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskStarted, events[2].Type)
	require.Equal(t, api.TaskTerminated, events[3].Type)
}

func (tc *TaskEventsTest) TestTaskEvents_FailedBatch(f *framework.F) {
	t := f.T()
	_, taskState := tc.waitUntilEvents(f, "failed_batch", 4)
	events := taskState.Events

	// Assert task did fail
	require.Truef(t, taskState.Failed, "task unexpectedly succeeded after %d events\n%s",
		len(events), formatEvents(events),
	)

	// Assert the expected type of events were emitted in a specific order
	// (based on v0.8.6)
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskDriverFailure, events[2].Type)
	require.Equal(t, api.TaskNotRestarting, events[3].Type)
	require.True(t, events[3].FailsTask)
}

// TestTaskEvents_CompletedLeader asserts the proper events are emitted for a
// non-leader task when its leader task completes.
func (tc *TaskEventsTest) TestTaskEvents_CompletedLeader(f *framework.F) {
	t := f.T()
	_, taskState := tc.waitUntilEvents(f, "completed_leader", 7)
	events := taskState.Events

	// Assert task did not fail
	require.Falsef(t, taskState.Failed, "task unexpectedly failed after %d events\n%s",
		len(events), formatEvents(events),
	)

	// Assert the expected type of events were emitted in a specific order
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskStarted, events[2].Type)
	require.Equal(t, api.TaskLeaderDead, events[3].Type)
	require.Equal(t, api.TaskKilling, events[4].Type)
	require.Equal(t, api.TaskTerminated, events[5].Type)
	require.Equal(t, api.TaskKilled, events[6].Type)
}

// TestTaskEvents_FailedSibling asserts the proper events are emitted for a
// task when another task in its task group fails.
func (tc *TaskEventsTest) TestTaskEvents_FailedSibling(f *framework.F) {
	t := f.T()
	alloc, taskState := tc.waitUntilEvents(f, "failed_sibling", 7)
	events := taskState.Events

	// Just because a sibling failed doesn't mean this task fails. It
	// should exit cleanly. (same as in v0.8.6)
	require.Falsef(t, taskState.Failed, "task unexpectedly failed after %d events\n%s",
		len(events), formatEvents(events),
	)

	// The alloc should be faied
	require.Equal(t, "failed", alloc.ClientStatus)

	// Assert the expected type of events were emitted in a specific order
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskStarted, events[2].Type)
	require.Equal(t, api.TaskSiblingFailed, events[3].Type)
	require.Equal(t, api.TaskKilling, events[4].Type)
	require.Equal(t, api.TaskTerminated, events[5].Type)
	require.Equal(t, api.TaskKilled, events[6].Type)
}
<commit_msg>e2e: fix flaky TaskEventsTest (#9114)<commit_after>package taskevents

import (
	"fmt"
	"strings"
	"time"

	"github.com/hashicorp/nomad/api"
	"github.com/hashicorp/nomad/e2e/framework"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"

	"github.com/hashicorp/nomad/e2e/e2eutil"
	"github.com/hashicorp/nomad/helper/uuid"
)

type TaskEventsTest struct {
	framework.TC
	jobIds []string
}

func init() {
	framework.AddSuites(&framework.TestSuite{
		Component:   "TaskEvents",
		CanRunLocal: true,
		Cases: []framework.TestCase{
			new(TaskEventsTest),
		},
	})
}

func (tc *TaskEventsTest) BeforeAll(f *framework.F) {
	e2eutil.WaitForLeader(f.T(), tc.Nomad())
	e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 1)
}

func (tc *TaskEventsTest) AfterEach(f *framework.F) {
	nomadClient := tc.Nomad()
	jobs := nomadClient.Jobs()
	// Stop all jobs in test
	for _, id := range tc.jobIds {
		jobs.Deregister(id, true, nil)
	}
	// Garbage collect
	nomadClient.System().GarbageCollect()
}

func formatEvents(events []*api.TaskEvent) string {
	estrs := make([]string, len(events))
	for i, e := range events {
		estrs[i] = fmt.Sprintf("%2d %-20s fail=%t msg=> %s", i, e.Type, e.FailsTask, e.DisplayMessage)
	}
	return strings.Join(estrs, "\n")
}

// waitUntilEvents submits a job and then waits until the expected number of
// events exist.
//
// The job name is used to load the job file from "input/${job}.nomad", and
// events are only inspected for tasks named the same as the job. That task's
// state is returned as well as the last allocation received.
func (tc *TaskEventsTest) waitUntilEvents(f *framework.F, jobName string, numEvents int) (*api.Allocation, *api.TaskState) {
	t := f.T()
	nomadClient := tc.Nomad()
	uuid := uuid.Generate()
	uniqJobId := jobName + uuid[0:8]
	tc.jobIds = append(tc.jobIds, uniqJobId)

	jobFile := fmt.Sprintf("taskevents/input/%s.nomad", jobName)
	allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, jobFile, uniqJobId, "")

	require.Len(t, allocs, 1)
	allocID := allocs[0].ID
	qo := &api.QueryOptions{
		WaitTime: time.Second,
	}

	// Capture state outside of wait to ease assertions once expected
	// number of events have been received.
	var alloc *api.Allocation
	var taskState *api.TaskState

	testutil.WaitForResultRetries(10, func() (bool, error) {
		a, meta, err := nomadClient.Allocations().Info(allocID, qo)
		if err != nil {
			return false, err
		}

		qo.WaitIndex = meta.LastIndex

		// Capture alloc and task state
		alloc = a
		taskState = a.TaskStates[jobName]
		if taskState == nil {
			return false, fmt.Errorf("task state not found for %s", jobName)
		}

		// Assert expected number of task events; we can't check for the exact
		// count because of a race where Allocation Unhealthy events can be
		// emitted when a peer task dies, but the caller can assert the
		// specific events and their order up to that point
		if len(taskState.Events) < numEvents {
			return false, fmt.Errorf("expected %d task events but found %d\n%s",
				numEvents, len(taskState.Events), formatEvents(taskState.Events),
			)
		}

		return true, nil
	}, func(err error) {
		t.Fatalf("task events error: %v", err)
	})

	return alloc, taskState
}

func (tc *TaskEventsTest) TestTaskEvents_SimpleBatch(f *framework.F) {
	t := f.T()
	_, taskState := tc.waitUntilEvents(f, "simple_batch", 4)
	events := taskState.Events

	// Assert task did not fail
	require.Falsef(t, taskState.Failed, "task unexpectedly failed after %d events\n%s",
		len(events), formatEvents(events),
	)

	// Assert the expected type of events were emitted in a specific order
	// (based on v0.8.6)
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskStarted, events[2].Type)
	require.Equal(t, api.TaskTerminated, events[3].Type)
}

func (tc *TaskEventsTest) TestTaskEvents_FailedBatch(f *framework.F) {
	t := f.T()
	_, taskState := tc.waitUntilEvents(f, "failed_batch", 4)
	events := taskState.Events

	// Assert task did fail
	require.Truef(t, taskState.Failed, "task unexpectedly succeeded after %d events\n%s",
		len(events), formatEvents(events),
	)

	// Assert the expected type of events were emitted in a specific order
	// (based on v0.8.6)
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskDriverFailure, events[2].Type)
	require.Equal(t, api.TaskNotRestarting, events[3].Type)
	require.True(t, events[3].FailsTask)
}

// TestTaskEvents_CompletedLeader asserts the proper events are emitted for a
// non-leader task when its leader task completes.
func (tc *TaskEventsTest) TestTaskEvents_CompletedLeader(f *framework.F) {
	t := f.T()
	_, taskState := tc.waitUntilEvents(f, "completed_leader", 7)
	events := taskState.Events

	// Assert task did not fail
	require.Falsef(t, taskState.Failed, "task unexpectedly failed after %d events\n%s",
		len(events), formatEvents(events),
	)

	// Assert the expected type of events were emitted in a specific order
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskStarted, events[2].Type)
	require.Equal(t, api.TaskLeaderDead, events[3].Type)
	require.Equal(t, api.TaskKilling, events[4].Type)
	require.Equal(t, api.TaskTerminated, events[5].Type)
	require.Equal(t, api.TaskKilled, events[6].Type)
}

// TestTaskEvents_FailedSibling asserts the proper events are emitted for a
// task when another task in its task group fails.
func (tc *TaskEventsTest) TestTaskEvents_FailedSibling(f *framework.F) {
	t := f.T()
	alloc, taskState := tc.waitUntilEvents(f, "failed_sibling", 7)
	events := taskState.Events

	// Just because a sibling failed doesn't mean this task fails. It
	// should exit cleanly. (same as in v0.8.6)
	require.Falsef(t, taskState.Failed, "task unexpectedly failed after %d events\n%s",
		len(events), formatEvents(events),
	)

	// The alloc should be faied
	require.Equal(t, "failed", alloc.ClientStatus)

	// Assert the expected type of events were emitted in a specific order
	require.Equal(t, api.TaskReceived, events[0].Type)
	require.Equal(t, api.TaskSetup, events[1].Type)
	require.Equal(t, api.TaskStarted, events[2].Type)
	require.Equal(t, api.TaskSiblingFailed, events[3].Type)
	require.Equal(t, api.TaskKilling, events[4].Type)
	require.Equal(t, api.TaskTerminated, events[5].Type)
	require.Equal(t, api.TaskKilled, events[6].Type)
}
<|endoftext|>