<commit_before>package lfs

import (
	"sync"
	"sync/atomic"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const (
	batchSize = 100
)

type Transferable interface {
	Check() (*objectResource, error)
	Transfer(CopyCallback) error
	Object() *objectResource
	Oid() string
	Size() int64
	Name() string
	SetObject(*objectResource)
}

// TransferQueue provides a queue that will allow concurrent transfers.
type TransferQueue struct {
	retrying      uint32
	meter         *ProgressMeter
	workers       int // Number of transfer workers to spawn
	transferKind  string
	errors        []error
	transferables map[string]Transferable
	retries       []Transferable
	batcher       *Batcher
	apic          chan Transferable // Channel for processing individual API requests
	transferc     chan Transferable // Channel for processing transfers
	retriesc      chan Transferable // Channel for processing retries
	errorc        chan error        // Channel for processing errors
	watchers      []chan string
	errorwait     sync.WaitGroup
	retrywait     sync.WaitGroup
	wait          sync.WaitGroup
}

// newTransferQueue builds a TransferQueue, allowing `workers` concurrent transfers.
func newTransferQueue(files int, size int64, dryRun bool) *TransferQueue {
	q := &TransferQueue{
		meter:         NewProgressMeter(files, size, dryRun),
		apic:          make(chan Transferable, batchSize),
		transferc:     make(chan Transferable, batchSize),
		retriesc:      make(chan Transferable, batchSize),
		errorc:        make(chan error),
		workers:       Config.ConcurrentTransfers(),
		transferables: make(map[string]Transferable),
	}

	q.errorwait.Add(1)
	q.retrywait.Add(1)

	q.run()

	return q
}

// Add adds a Transferable to the transfer queue.
func (q *TransferQueue) Add(t Transferable) {
	q.wait.Add(1)
	q.transferables[t.Oid()] = t

	if q.batcher != nil {
		q.batcher.Add(t)
		return
	}

	q.apic <- t
}

// Wait waits for the queue to finish processing all transfers. Once Wait is
// called, Add will no longer add transferables to the queue. Any failed
// transfers will be automatically retried once.
func (q *TransferQueue) Wait() {
	if q.batcher != nil {
		q.batcher.Exit()
	}

	q.wait.Wait()

	// Handle any retries
	close(q.retriesc)
	q.retrywait.Wait()
	atomic.StoreUint32(&q.retrying, 1)

	if len(q.retries) > 0 && q.batcher != nil {
		tracerx.Printf("tq: retrying %d failed transfers", len(q.retries))
		for _, t := range q.retries {
			q.Add(t)
		}
		q.batcher.Exit()
		q.wait.Wait()
	}

	atomic.StoreUint32(&q.retrying, 0)

	close(q.apic)
	close(q.transferc)
	close(q.errorc)

	for _, watcher := range q.watchers {
		close(watcher)
	}

	q.meter.Finish()
	q.errorwait.Wait()
}

// Watch returns a channel where the queue will write the OID of each transfer
// as it completes. The channel will be closed when the queue finishes processing.
func (q *TransferQueue) Watch() chan string {
	c := make(chan string, batchSize)
	q.watchers = append(q.watchers, c)
	return c
}

// individualApiRoutine processes the queue of transfers one at a time by making
// a POST call for each object, feeding the results to the transfer workers.
// If configured, the object transfers can still happen concurrently, the
// sequential nature here is only for the meta POST calls.
func (q *TransferQueue) individualApiRoutine(apiWaiter chan interface{}) {
	for t := range q.apic {
		obj, err := t.Check()
		if err != nil {
			if q.canRetry(err) {
				q.retry(t)
			} else {
				q.errorc <- err
			}
			q.wait.Done()
			continue
		}

		if apiWaiter != nil { // Signal to launch more individual api workers
			q.meter.Start()
			select {
			case apiWaiter <- 1:
			default:
			}
		}

		if obj != nil {
			t.SetObject(obj)
			q.meter.Add(t.Name())
			q.transferc <- t
		} else {
			q.meter.Skip(t.Size())
			q.wait.Done()
		}
	}
}

// legacyFallback is used when a batch request is made to a server that does
// not support the batch endpoint. When this happens, the Transferables are
// fed from the batcher into apic to be processed individually.
func (q *TransferQueue) legacyFallback(failedBatch []Transferable) {
	tracerx.Printf("tq: batch api not implemented, falling back to individual")

	q.launchIndividualApiRoutines()

	for _, t := range failedBatch {
		q.apic <- t
	}

	for {
		batch := q.batcher.Next()
		if batch == nil {
			break
		}

		for _, t := range batch {
			q.apic <- t
		}
	}
}

// batchApiRoutine processes the queue of transfers using the batch endpoint,
// making only one POST call for all objects. The results are then handed
// off to the transfer workers.
func (q *TransferQueue) batchApiRoutine() {
	var startProgress sync.Once

	for {
		batch := q.batcher.Next()
		if batch == nil {
			break
		}

		tracerx.Printf("tq: sending batch of size %d", len(batch))

		transfers := make([]*objectResource, 0, len(batch))
		for _, t := range batch {
			transfers = append(transfers, &objectResource{Oid: t.Oid(), Size: t.Size()})
		}

		objects, err := Batch(transfers, q.transferKind)
		if err != nil {
			if IsNotImplementedError(err) {
				git.Config.SetLocal("", "lfs.batch", "false")

				go q.legacyFallback(batch)
				return
			}

			if q.canRetry(err) {
				for _, t := range batch {
					q.retry(t)
				}
			} else {
				q.errorc <- err
			}

			q.wait.Add(-len(transfers))
			continue
		}

		startProgress.Do(q.meter.Start)

		for _, o := range objects {
			if _, ok := o.Rel(q.transferKind); ok {
				// This object has an error
				if o.Error != nil {
					q.errorc <- Error(o.Error)
					q.meter.Skip(o.Size)
					q.wait.Done()
					continue
				}

				// This object needs to be transferred
				if transfer, ok := q.transferables[o.Oid]; ok {
					transfer.SetObject(o)
					q.meter.Add(transfer.Name())
					q.transferc <- transfer
				} else {
					q.meter.Skip(transfer.Size())
					q.wait.Done()
				}
			} else {
				q.meter.Skip(o.Size)
				q.wait.Done()
			}
		}
	}
}

// This goroutine collects errors returned from transfers
func (q *TransferQueue) errorCollector() {
	for err := range q.errorc {
		q.errors = append(q.errors, err)
	}
	q.errorwait.Done()
}

func (q *TransferQueue) retryCollector() {
	for t := range q.retriesc {
		q.retries = append(q.retries, t)
	}
	q.retrywait.Done()
}

func (q *TransferQueue) transferWorker() {
	for transfer := range q.transferc {
		cb := func(total, read int64, current int) error {
			q.meter.TransferBytes(q.transferKind, transfer.Name(), read, total, current)
			return nil
		}

		if err := transfer.Transfer(cb); err != nil {
			if q.canRetry(err) {
				tracerx.Printf("tq: retrying object %s", transfer.Oid())
				q.retry(transfer)
			} else {
				q.errorc <- err
			}
		} else {
			oid := transfer.Oid()
			for _, c := range q.watchers {
				c <- oid
			}
		}

		q.meter.FinishTransfer(transfer.Name())

		q.wait.Done()
	}
}

// launchIndividualApiRoutines first launches a single api worker. When it
// receives the first successful api request it launches workers - 1 more
// workers. This prevents being prompted for credentials multiple times at once
// when they're needed.
func (q *TransferQueue) launchIndividualApiRoutines() {
	go func() {
		apiWaiter := make(chan interface{})
		go q.individualApiRoutine(apiWaiter)

		<-apiWaiter

		for i := 0; i < q.workers-1; i++ {
			go q.individualApiRoutine(nil)
		}
	}()
}

// run starts the transfer queue, doing individual or batch transfers depending
// on the Config.BatchTransfer() value. run will transfer files sequentially or
// concurrently depending on the Config.ConcurrentTransfers() value.
func (q *TransferQueue) run() {
	go q.errorCollector()
	go q.retryCollector()

	tracerx.Printf("tq: starting %d transfer workers", q.workers)
	for i := 0; i < q.workers; i++ {
		go q.transferWorker()
	}

	if Config.BatchTransfer() {
		tracerx.Printf("tq: running as batched queue, batch size of %d", batchSize)
		q.batcher = NewBatcher(batchSize)
		go q.batchApiRoutine()
	} else {
		tracerx.Printf("tq: running as individual queue")
		q.launchIndividualApiRoutines()
	}
}

func (q *TransferQueue) retry(t Transferable) {
	q.retriesc <- t
}

func (q *TransferQueue) canRetry(err error) bool {
	if !IsRetriableError(err) || atomic.LoadUint32(&q.retrying) == 1 {
		return false
	}

	return true
}

// Errors returns any errors encountered during transfer.
func (q *TransferQueue) Errors() []error {
	return q.errors
}
<commit_msg>ンンンンン ンンンン<commit_after>package lfs

import (
	"sync"
	"sync/atomic"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const (
	batchSize = 100
)

type Transferable interface {
	Check() (*objectResource, error)
	Transfer(CopyCallback) error
	Object() *objectResource
	Oid() string
	Size() int64
	Name() string
	SetObject(*objectResource)
}

// TransferQueue provides a queue that will allow concurrent transfers.
type TransferQueue struct {
	retrying      uint32
	meter         *ProgressMeter
	workers       int // Number of transfer workers to spawn
	transferKind  string
	errors        []error
	transferables map[string]Transferable
	retries       []Transferable
	batcher       *Batcher
	apic          chan Transferable // Channel for processing individual API requests
	transferc     chan Transferable // Channel for processing transfers
	retriesc      chan Transferable // Channel for processing retries
	errorc        chan error        // Channel for processing errors
	watchers      []chan string
	errorwait     sync.WaitGroup
	retrywait     sync.WaitGroup
	wait          sync.WaitGroup
}

// newTransferQueue builds a TransferQueue, allowing `workers` concurrent transfers.
func newTransferQueue(files int, size int64, dryRun bool) *TransferQueue {
	q := &TransferQueue{
		meter:         NewProgressMeter(files, size, dryRun),
		apic:          make(chan Transferable, batchSize),
		transferc:     make(chan Transferable, batchSize),
		retriesc:      make(chan Transferable, batchSize),
		errorc:        make(chan error),
		workers:       Config.ConcurrentTransfers(),
		transferables: make(map[string]Transferable),
	}

	q.errorwait.Add(1)
	q.retrywait.Add(1)

	q.run()

	return q
}

// Add adds a Transferable to the transfer queue.
func (q *TransferQueue) Add(t Transferable) {
	q.wait.Add(1)
	q.transferables[t.Oid()] = t

	if q.batcher != nil {
		q.batcher.Add(t)
		return
	}

	q.apic <- t
}

// Wait waits for the queue to finish processing all transfers. Once Wait is
// called, Add will no longer add transferables to the queue. Any failed
// transfers will be automatically retried once.
func (q *TransferQueue) Wait() {
	if q.batcher != nil {
		q.batcher.Exit()
	}

	q.wait.Wait()

	// Handle any retries
	close(q.retriesc)
	q.retrywait.Wait()
	atomic.StoreUint32(&q.retrying, 1)

	if len(q.retries) > 0 {
		tracerx.Printf("tq: retrying %d failed transfers", len(q.retries))
		for _, t := range q.retries {
			q.Add(t)
		}
		if q.batcher != nil {
			q.batcher.Exit()
		}
		q.wait.Wait()
	}

	atomic.StoreUint32(&q.retrying, 0)

	close(q.apic)
	close(q.transferc)
	close(q.errorc)

	for _, watcher := range q.watchers {
		close(watcher)
	}

	q.meter.Finish()
	q.errorwait.Wait()
}

// Watch returns a channel where the queue will write the OID of each transfer
// as it completes. The channel will be closed when the queue finishes processing.
func (q *TransferQueue) Watch() chan string {
	c := make(chan string, batchSize)
	q.watchers = append(q.watchers, c)
	return c
}

// individualApiRoutine processes the queue of transfers one at a time by making
// a POST call for each object, feeding the results to the transfer workers.
// If configured, the object transfers can still happen concurrently, the
// sequential nature here is only for the meta POST calls.
func (q *TransferQueue) individualApiRoutine(apiWaiter chan interface{}) {
	for t := range q.apic {
		obj, err := t.Check()
		if err != nil {
			if q.canRetry(err) {
				q.retry(t)
			} else {
				q.errorc <- err
			}
			q.wait.Done()
			continue
		}

		if apiWaiter != nil { // Signal to launch more individual api workers
			q.meter.Start()
			select {
			case apiWaiter <- 1:
			default:
			}
		}

		if obj != nil {
			t.SetObject(obj)
			q.meter.Add(t.Name())
			q.transferc <- t
		} else {
			q.meter.Skip(t.Size())
			q.wait.Done()
		}
	}
}

// legacyFallback is used when a batch request is made to a server that does
// not support the batch endpoint. When this happens, the Transferables are
// fed from the batcher into apic to be processed individually.
func (q *TransferQueue) legacyFallback(failedBatch []Transferable) {
	tracerx.Printf("tq: batch api not implemented, falling back to individual")

	q.launchIndividualApiRoutines()

	for _, t := range failedBatch {
		q.apic <- t
	}

	for {
		batch := q.batcher.Next()
		if batch == nil {
			break
		}

		for _, t := range batch {
			q.apic <- t
		}
	}
}

// batchApiRoutine processes the queue of transfers using the batch endpoint,
// making only one POST call for all objects. The results are then handed
// off to the transfer workers.
func (q *TransferQueue) batchApiRoutine() {
	var startProgress sync.Once

	for {
		batch := q.batcher.Next()
		if batch == nil {
			break
		}

		tracerx.Printf("tq: sending batch of size %d", len(batch))

		transfers := make([]*objectResource, 0, len(batch))
		for _, t := range batch {
			transfers = append(transfers, &objectResource{Oid: t.Oid(), Size: t.Size()})
		}

		objects, err := Batch(transfers, q.transferKind)
		if err != nil {
			if IsNotImplementedError(err) {
				git.Config.SetLocal("", "lfs.batch", "false")

				go q.legacyFallback(batch)
				return
			}

			if q.canRetry(err) {
				for _, t := range batch {
					q.retry(t)
				}
			} else {
				q.errorc <- err
			}

			q.wait.Add(-len(transfers))
			continue
		}

		startProgress.Do(q.meter.Start)

		for _, o := range objects {
			if _, ok := o.Rel(q.transferKind); ok {
				// This object has an error
				if o.Error != nil {
					q.errorc <- Error(o.Error)
					q.meter.Skip(o.Size)
					q.wait.Done()
					continue
				}

				// This object needs to be transferred
				if transfer, ok := q.transferables[o.Oid]; ok {
					transfer.SetObject(o)
					q.meter.Add(transfer.Name())
					q.transferc <- transfer
				} else {
					q.meter.Skip(transfer.Size())
					q.wait.Done()
				}
			} else {
				q.meter.Skip(o.Size)
				q.wait.Done()
			}
		}
	}
}

// This goroutine collects errors returned from transfers
func (q *TransferQueue) errorCollector() {
	for err := range q.errorc {
		q.errors = append(q.errors, err)
	}
	q.errorwait.Done()
}

func (q *TransferQueue) retryCollector() {
	for t := range q.retriesc {
		q.retries = append(q.retries, t)
	}
	q.retrywait.Done()
}

func (q *TransferQueue) transferWorker() {
	for transfer := range q.transferc {
		cb := func(total, read int64, current int) error {
			q.meter.TransferBytes(q.transferKind, transfer.Name(), read, total, current)
			return nil
		}

		if err := transfer.Transfer(cb); err != nil {
			if q.canRetry(err) {
				tracerx.Printf("tq: retrying object %s", transfer.Oid())
				q.retry(transfer)
			} else {
				q.errorc <- err
			}
		} else {
			oid := transfer.Oid()
			for _, c := range q.watchers {
				c <- oid
			}
		}

		q.meter.FinishTransfer(transfer.Name())

		q.wait.Done()
	}
}

// launchIndividualApiRoutines first launches a single api worker. When it
// receives the first successful api request it launches workers - 1 more
// workers. This prevents being prompted for credentials multiple times at once
// when they're needed.
func (q *TransferQueue) launchIndividualApiRoutines() {
	go func() {
		apiWaiter := make(chan interface{})
		go q.individualApiRoutine(apiWaiter)

		<-apiWaiter

		for i := 0; i < q.workers-1; i++ {
			go q.individualApiRoutine(nil)
		}
	}()
}

// run starts the transfer queue, doing individual or batch transfers depending
// on the Config.BatchTransfer() value. run will transfer files sequentially or
// concurrently depending on the Config.ConcurrentTransfers() value.
func (q *TransferQueue) run() {
	go q.errorCollector()
	go q.retryCollector()

	tracerx.Printf("tq: starting %d transfer workers", q.workers)
	for i := 0; i < q.workers; i++ {
		go q.transferWorker()
	}

	if Config.BatchTransfer() {
		tracerx.Printf("tq: running as batched queue, batch size of %d", batchSize)
		q.batcher = NewBatcher(batchSize)
		go q.batchApiRoutine()
	} else {
		tracerx.Printf("tq: running as individual queue")
		q.launchIndividualApiRoutines()
	}
}

func (q *TransferQueue) retry(t Transferable) {
	q.retriesc <- t
}

func (q *TransferQueue) canRetry(err error) bool {
	if !IsRetriableError(err) || atomic.LoadUint32(&q.retrying) == 1 {
		return false
	}

	return true
}

// Errors returns any errors encountered during transfer.
func (q *TransferQueue) Errors() []error {
	return q.errors
}
<|endoftext|>


<commit_before>package curses

/*
#include <ncurses.h>
#include <locale.h>
#cgo LDFLAGS: -lncurses
void swapOutput() {
  FILE* temp = stdout;
  stdout = stderr;
  stderr = temp;
}
*/
import "C"

import (
	"os"
	"os/signal"
	"syscall"
	"time"
	"unicode/utf8"
)

// Types of user action
const (
	Rune = iota

	CtrlA
	CtrlB
	CtrlC
	CtrlD
	CtrlE
	CtrlF
	CtrlG
	CtrlH
	Tab
	CtrlJ
	CtrlK
	CtrlL
	CtrlM
	CtrlN
	CtrlO
	CtrlP
	CtrlQ
	CtrlR
	CtrlS
	CtrlT
	CtrlU
	CtrlV
	CtrlW
	CtrlX
	CtrlY
	CtrlZ
	ESC

	Invalid
	Mouse

	BTab

	Del
	PgUp
	PgDn

	F1
	F2
	F3
	F4

	AltBS
	AltA
	AltB
	AltC
	AltD
	AltE
	AltF

	AltZ = AltA + 'z' - 'a'
)

// Pallete
const (
	ColNormal = iota
	ColPrompt
	ColMatch
	ColCurrent
	ColCurrentMatch
	ColSpinner
	ColInfo
	ColCursor
	ColSelected
	ColUser
)

const (
	doubleClickDuration = 500 * time.Millisecond
)

type Event struct {
	Type       int
	Char       rune
	MouseEvent *MouseEvent
}

type MouseEvent struct {
	Y      int
	X      int
	S      int
	Down   bool
	Double bool
	Mod    bool
}

var (
	_buf          []byte
	_in           *os.File
	_color        func(int, bool) C.int
	_colorMap     map[int]int
	_prevDownTime time.Time
	_prevDownY    int
	_clickY       []int
	DarkBG        C.short
)

func init() {
	_prevDownTime = time.Unix(0, 0)
	_clickY = []int{}
	_colorMap = make(map[int]int)
}

func attrColored(pair int, bold bool) C.int {
	var attr C.int
	if pair > ColNormal {
		attr = C.COLOR_PAIR(C.int(pair))
	}
	if bold {
		attr = attr | C.A_BOLD
	}
	return attr
}

func attrMono(pair int, bold bool) C.int {
	var attr C.int
	switch pair {
	case ColCurrent:
		if bold {
			attr = C.A_REVERSE
		}
	case ColMatch:
		attr = C.A_UNDERLINE
	case ColCurrentMatch:
		attr = C.A_UNDERLINE | C.A_REVERSE
	}
	if bold {
		attr = attr | C.A_BOLD
	}
	return attr
}

func MaxX() int {
	return int(C.COLS)
}

func MaxY() int {
	return int(C.LINES)
}

func getch(nonblock bool) int {
	b := make([]byte, 1)
	syscall.SetNonblock(int(_in.Fd()), nonblock)
	_, err := _in.Read(b)
	if err != nil {
		return -1
	}
	return int(b[0])
}

func Init(color bool, color256 bool, black bool, mouse bool) {
	{
		in, err := os.OpenFile("/dev/tty", syscall.O_RDONLY, 0)
		if err != nil {
			panic("Failed to open /dev/tty")
		}
		_in = in
		// Break STDIN
		// syscall.Dup2(int(in.Fd()), int(os.Stdin.Fd()))
	}

	C.swapOutput()

	C.setlocale(C.LC_ALL, C.CString(""))
	C.initscr()
	if mouse {
		C.mousemask(C.ALL_MOUSE_EVENTS, nil)
	}
	C.cbreak()
	C.noecho()
	C.raw() // stty dsusp undef

	intChan := make(chan os.Signal, 1)
	signal.Notify(intChan, os.Interrupt, os.Kill)
	go func() {
		<-intChan
		Close()
		os.Exit(1)
	}()

	if color {
		C.start_color()
		var bg C.short
		if black {
			bg = C.COLOR_BLACK
		} else {
			C.use_default_colors()
			bg = -1
		}
		if color256 {
			DarkBG = 236
			C.init_pair(ColPrompt, 110, bg)
			C.init_pair(ColMatch, 108, bg)
			C.init_pair(ColCurrent, 254, DarkBG)
			C.init_pair(ColCurrentMatch, 151, DarkBG)
			C.init_pair(ColSpinner, 148, bg)
			C.init_pair(ColInfo, 144, bg)
			C.init_pair(ColCursor, 161, DarkBG)
			C.init_pair(ColSelected, 168, DarkBG)
		} else {
			DarkBG = C.COLOR_BLACK
			C.init_pair(ColPrompt, C.COLOR_BLUE, bg)
			C.init_pair(ColMatch, C.COLOR_GREEN, bg)
			C.init_pair(ColCurrent, C.COLOR_YELLOW, DarkBG)
			C.init_pair(ColCurrentMatch, C.COLOR_GREEN, DarkBG)
			C.init_pair(ColSpinner, C.COLOR_GREEN, bg)
			C.init_pair(ColInfo, C.COLOR_WHITE, bg)
			C.init_pair(ColCursor, C.COLOR_RED, DarkBG)
			C.init_pair(ColSelected, C.COLOR_MAGENTA, DarkBG)
		}
		_color = attrColored
	} else {
		_color = attrMono
	}
}

func Close() {
	C.endwin()
	C.swapOutput()
}

func GetBytes() []byte {
	c := getch(false)
	_buf = append(_buf, byte(c))

	for {
		c = getch(true)
		if c == -1 {
			break
		}
		_buf = append(_buf, byte(c))
	}

	return _buf
}

// 27 (91 79) 77 type x y
func mouseSequence(sz *int) Event {
	if len(_buf) < 6 {
		return Event{Invalid, 0, nil}
	}
	*sz = 6
	switch _buf[3] {
	case 32, 36, 40, 48, // mouse-down / shift / cmd / ctrl
		35, 39, 43, 51: // mouse-up / shift / cmd / ctrl
		mod := _buf[3] >= 36
		down := _buf[3]%2 == 0
		x := int(_buf[4] - 33)
		y := int(_buf[5] - 33)
		double := false
		if down {
			now := time.Now()
			if now.Sub(_prevDownTime) < doubleClickDuration {
				_clickY = append(_clickY, y)
			} else {
				_clickY = []int{y}
			}
			_prevDownTime = now
		} else {
			if len(_clickY) > 1 && _clickY[0] == _clickY[1] &&
				time.Now().Sub(_prevDownTime) < doubleClickDuration {
				double = true
			}
		}
		return Event{Mouse, 0, &MouseEvent{y, x, 0, down, double, mod}}
	case 96, 100, 104, 112, // scroll-up / shift / cmd / ctrl
		97, 101, 105, 113: // scroll-down / shift / cmd / ctrl
		mod := _buf[3] >= 100
		s := 1 - int(_buf[3]%2)*2
		return Event{Mouse, 0, &MouseEvent{0, 0, s, false, false, mod}}
	}
	return Event{Invalid, 0, nil}
}

func escSequence(sz *int) Event {
	if len(_buf) < 2 {
		return Event{ESC, 0, nil}
	}
	*sz = 2
	switch _buf[1] {
	case 98:
		return Event{AltB, 0, nil}
	case 100:
		return Event{AltD, 0, nil}
	case 102:
		return Event{AltF, 0, nil}
	case 127:
		return Event{AltBS, 0, nil}
	case 91, 79:
		if len(_buf) < 3 {
			return Event{Invalid, 0, nil}
		}
		*sz = 3
		switch _buf[2] {
		case 68:
			return Event{CtrlB, 0, nil}
		case 67:
			return Event{CtrlF, 0, nil}
		case 66:
			return Event{CtrlJ, 0, nil}
		case 65:
			return Event{CtrlK, 0, nil}
		case 90:
			return Event{BTab, 0, nil}
		case 72:
			return Event{CtrlA, 0, nil}
		case 70:
			return Event{CtrlE, 0, nil}
		case 77:
			return mouseSequence(sz)
		case 80:
			return Event{F1, 0, nil}
		case 81:
			return Event{F2, 0, nil}
		case 82:
			return Event{F3, 0, nil}
		case 83:
			return Event{F4, 0, nil}
		case 49, 50, 51, 52, 53, 54:
			if len(_buf) < 4 {
				return Event{Invalid, 0, nil}
			}
			*sz = 4
			switch _buf[2] {
			case 50:
				return Event{Invalid, 0, nil} // INS
			case 51:
				return Event{Del, 0, nil}
			case 52:
				return Event{CtrlE, 0, nil}
			case 53:
				return Event{PgUp, 0, nil}
			case 54:
				return Event{PgDn, 0, nil}
			case 49:
				switch _buf[3] {
				case 126:
					return Event{CtrlA, 0, nil}
				case 59:
					if len(_buf) != 6 {
						return Event{Invalid, 0, nil}
					}
					*sz = 6
					switch _buf[4] {
					case 50:
						switch _buf[5] {
						case 68:
							return Event{CtrlA, 0, nil}
						case 67:
							return Event{CtrlE, 0, nil}
						}
					case 53:
						switch _buf[5] {
						case 68:
							return Event{AltB, 0, nil}
						case 67:
							return Event{AltF, 0, nil}
						}
					} // _buf[4]
				} // _buf[3]
			} // _buf[2]
		} // _buf[2]
	} // _buf[1]
	if _buf[1] >= 'a' && _buf[1] <= 'z' {
		return Event{AltA + int(_buf[1]) - 'a', 0, nil}
	}
	return Event{Invalid, 0, nil}
}

func GetChar() Event {
	if len(_buf) == 0 {
		_buf = GetBytes()
	}
	if len(_buf) == 0 {
		panic("Empty _buffer")
	}

	sz := 1
	defer func() {
		_buf = _buf[sz:]
	}()

	switch _buf[0] {
	case CtrlC, CtrlG, CtrlQ:
		return Event{CtrlC, 0, nil}
	case 127:
		return Event{CtrlH, 0, nil}
	case ESC:
		return escSequence(&sz)
	}

	// CTRL-A ~ CTRL-Z
	if _buf[0] <= CtrlZ {
		return Event{int(_buf[0]), 0, nil}
	}
	r, rsz := utf8.DecodeRune(_buf)
	if r == utf8.RuneError {
		return Event{ESC, 0, nil}
	}
	sz = rsz
	return Event{Rune, r, nil}
}

func Move(y int, x int) {
	C.move(C.int(y), C.int(x))
}

func MoveAndClear(y int, x int) {
	Move(y, x)
	C.clrtoeol()
}

func Print(text string) {
	C.addstr(C.CString(text))
}

func CPrint(pair int, bold bool, text string) {
	attr := _color(pair, bold)
	C.attron(attr)
	Print(text)
	C.attroff(attr)
}

func Clear() {
	C.clear()
}

func Endwin() {
	C.endwin()
}

func Refresh() {
	C.refresh()
}

func PairFor(fg int, bg int) int {
	key := (fg << 8) + bg
	if found, prs := _colorMap[key]; prs {
		return found
	}

	id := len(_colorMap) + ColUser
	C.init_pair(C.short(id), C.short(fg), C.short(bg))
	_colorMap[key] = id
	return id
}
<commit_msg>Remove unused variable<commit_after>package curses

/*
#include <ncurses.h>
#include <locale.h>
#cgo LDFLAGS: -lncurses
void swapOutput() {
  FILE* temp = stdout;
  stdout = stderr;
  stderr = temp;
}
*/
import "C"

import (
	"os"
	"os/signal"
	"syscall"
	"time"
	"unicode/utf8"
)

// Types of user action
const (
	Rune = iota

	CtrlA
	CtrlB
	CtrlC
	CtrlD
	CtrlE
	CtrlF
	CtrlG
	CtrlH
	Tab
	CtrlJ
	CtrlK
	CtrlL
	CtrlM
	CtrlN
	CtrlO
	CtrlP
	CtrlQ
	CtrlR
	CtrlS
	CtrlT
	CtrlU
	CtrlV
	CtrlW
	CtrlX
	CtrlY
	CtrlZ
	ESC

	Invalid
	Mouse

	BTab

	Del
	PgUp
	PgDn

	F1
	F2
	F3
	F4

	AltBS
	AltA
	AltB
	AltC
	AltD
	AltE
	AltF

	AltZ = AltA + 'z' - 'a'
)

// Pallete
const (
	ColNormal = iota
	ColPrompt
	ColMatch
	ColCurrent
	ColCurrentMatch
	ColSpinner
	ColInfo
	ColCursor
	ColSelected
	ColUser
)

const (
	doubleClickDuration = 500 * time.Millisecond
)

type Event struct {
	Type       int
	Char       rune
	MouseEvent *MouseEvent
}

type MouseEvent struct {
	Y      int
	X      int
	S      int
	Down   bool
	Double bool
	Mod    bool
}

var (
	_buf          []byte
	_in           *os.File
	_color        func(int, bool) C.int
	_colorMap     map[int]int
	_prevDownTime time.Time
	_clickY       []int
	DarkBG        C.short
)

func init() {
	_prevDownTime = time.Unix(0, 0)
	_clickY = []int{}
	_colorMap = make(map[int]int)
}

func attrColored(pair int, bold bool) C.int {
	var attr C.int
	if pair > ColNormal {
		attr = C.COLOR_PAIR(C.int(pair))
	}
	if bold {
		attr = attr | C.A_BOLD
	}
	return attr
}

func attrMono(pair int, bold bool) C.int {
	var attr C.int
	switch pair {
	case ColCurrent:
		if bold {
			attr = C.A_REVERSE
		}
	case ColMatch:
		attr = C.A_UNDERLINE
	case ColCurrentMatch:
		attr = C.A_UNDERLINE | C.A_REVERSE
	}
	if bold {
		attr = attr | C.A_BOLD
	}
	return attr
}

func MaxX() int {
	return int(C.COLS)
}

func MaxY() int {
	return int(C.LINES)
}

func getch(nonblock bool) int {
	b := make([]byte, 1)
	syscall.SetNonblock(int(_in.Fd()), nonblock)
	_, err := _in.Read(b)
	if err != nil {
		return -1
	}
	return int(b[0])
}

func Init(color bool, color256 bool, black bool, mouse bool) {
	{
		in, err := os.OpenFile("/dev/tty", syscall.O_RDONLY, 0)
		if err != nil {
			panic("Failed to open /dev/tty")
		}
		_in = in
		// Break STDIN
		// syscall.Dup2(int(in.Fd()), int(os.Stdin.Fd()))
	}

	C.swapOutput()

	C.setlocale(C.LC_ALL, C.CString(""))
	C.initscr()
	if mouse {
		C.mousemask(C.ALL_MOUSE_EVENTS, nil)
	}
	C.cbreak()
	C.noecho()
	C.raw() // stty dsusp undef

	intChan := make(chan os.Signal, 1)
	signal.Notify(intChan, os.Interrupt, os.Kill)
	go func() {
		<-intChan
		Close()
		os.Exit(1)
	}()

	if color {
		C.start_color()
		var bg C.short
		if black {
			bg = C.COLOR_BLACK
		} else {
			C.use_default_colors()
			bg = -1
		}
		if color256 {
			DarkBG = 236
			C.init_pair(ColPrompt, 110, bg)
			C.init_pair(ColMatch, 108, bg)
			C.init_pair(ColCurrent, 254, DarkBG)
			C.init_pair(ColCurrentMatch, 151, DarkBG)
			C.init_pair(ColSpinner, 148, bg)
			C.init_pair(ColInfo, 144, bg)
			C.init_pair(ColCursor, 161, DarkBG)
			C.init_pair(ColSelected, 168, DarkBG)
		} else {
			DarkBG = C.COLOR_BLACK
			C.init_pair(ColPrompt, C.COLOR_BLUE, bg)
			C.init_pair(ColMatch, C.COLOR_GREEN, bg)
			C.init_pair(ColCurrent, C.COLOR_YELLOW, DarkBG)
			C.init_pair(ColCurrentMatch, C.COLOR_GREEN, DarkBG)
			C.init_pair(ColSpinner, C.COLOR_GREEN, bg)
			C.init_pair(ColInfo, C.COLOR_WHITE, bg)
			C.init_pair(ColCursor, C.COLOR_RED, DarkBG)
			C.init_pair(ColSelected, C.COLOR_MAGENTA, DarkBG)
		}
		_color = attrColored
	} else {
		_color = attrMono
	}
}

func Close() {
	C.endwin()
	C.swapOutput()
}

func GetBytes() []byte {
	c := getch(false)
	_buf = append(_buf, byte(c))

	for {
		c = getch(true)
		if c == -1 {
			break
		}
		_buf = append(_buf, byte(c))
	}

	return _buf
}

// 27 (91 79) 77 type x y
func mouseSequence(sz *int) Event {
	if len(_buf) < 6 {
		return Event{Invalid, 0, nil}
	}
	*sz = 6
	switch _buf[3] {
	case 32, 36, 40, 48, // mouse-down / shift / cmd / ctrl
		35, 39, 43, 51: // mouse-up / shift / cmd / ctrl
		mod := _buf[3] >= 36
		down := _buf[3]%2 == 0
		x := int(_buf[4] - 33)
		y := int(_buf[5] - 33)
		double := false
		if down {
			now := time.Now()
			if now.Sub(_prevDownTime) < doubleClickDuration {
				_clickY = append(_clickY, y)
			} else {
				_clickY = []int{y}
			}
			_prevDownTime = now
		} else {
			if len(_clickY) > 1 && _clickY[0] == _clickY[1] &&
				time.Now().Sub(_prevDownTime) < doubleClickDuration {
				double = true
			}
		}
		return Event{Mouse, 0, &MouseEvent{y, x, 0, down, double, mod}}
	case 96, 100, 104, 112, // scroll-up / shift / cmd / ctrl
		97, 101, 105, 113: // scroll-down / shift / cmd / ctrl
		mod := _buf[3] >= 100
		s := 1 - int(_buf[3]%2)*2
		return Event{Mouse, 0, &MouseEvent{0, 0, s, false, false, mod}}
	}
	return Event{Invalid, 0, nil}
}

func escSequence(sz *int) Event {
	if len(_buf) < 2 {
		return Event{ESC, 0, nil}
	}
	*sz = 2
	switch _buf[1] {
	case 98:
		return Event{AltB, 0, nil}
	case 100:
		return Event{AltD, 0, nil}
	case 102:
		return Event{AltF, 0, nil}
	case 127:
		return Event{AltBS, 0, nil}
	case 91, 79:
		if len(_buf) < 3 {
			return Event{Invalid, 0, nil}
		}
		*sz = 3
		switch _buf[2] {
		case 68:
			return Event{CtrlB, 0, nil}
		case 67:
			return Event{CtrlF, 0, nil}
		case 66:
			return Event{CtrlJ, 0, nil}
		case 65:
			return Event{CtrlK, 0, nil}
		case 90:
			return Event{BTab, 0, nil}
		case 72:
			return Event{CtrlA, 0, nil}
		case 70:
			return Event{CtrlE, 0, nil}
		case 77:
			return mouseSequence(sz)
		case 80:
			return Event{F1, 0, nil}
		case 81:
			return Event{F2, 0, nil}
		case 82:
			return Event{F3, 0, nil}
		case 83:
			return Event{F4, 0, nil}
		case 49, 50, 51, 52, 53, 54:
			if len(_buf) < 4 {
				return Event{Invalid, 0, nil}
			}
			*sz = 4
			switch _buf[2] {
			case 50:
				return Event{Invalid, 0, nil} // INS
			case 51:
				return Event{Del, 0, nil}
			case 52:
				return Event{CtrlE, 0, nil}
			case 53:
				return Event{PgUp, 0, nil}
			case 54:
				return Event{PgDn, 0, nil}
			case 49:
				switch _buf[3] {
				case 126:
					return Event{CtrlA, 0, nil}
				case 59:
					if len(_buf) != 6 {
						return Event{Invalid, 0, nil}
					}
					*sz = 6
					switch _buf[4] {
					case 50:
						switch _buf[5] {
						case 68:
							return Event{CtrlA, 0, nil}
						case 67:
							return Event{CtrlE, 0, nil}
						}
					case 53:
						switch _buf[5] {
						case 68:
							return Event{AltB, 0, nil}
						case 67:
							return Event{AltF, 0, nil}
						}
					} // _buf[4]
				} // _buf[3]
			} // _buf[2]
		} // _buf[2]
	} // _buf[1]
	if _buf[1] >= 'a' && _buf[1] <= 'z' {
		return Event{AltA + int(_buf[1]) - 'a', 0, nil}
	}
	return Event{Invalid, 0, nil}
}

func GetChar() Event {
	if len(_buf) == 0 {
		_buf = GetBytes()
	}
	if len(_buf) == 0 {
		panic("Empty _buffer")
	}

	sz := 1
	defer func() {
		_buf = _buf[sz:]
	}()

	switch _buf[0] {
	case CtrlC, CtrlG, CtrlQ:
		return Event{CtrlC, 0, nil}
	case 127:
		return Event{CtrlH, 0, nil}
	case ESC:
		return escSequence(&sz)
	}

	// CTRL-A ~ CTRL-Z
	if _buf[0] <= CtrlZ {
		return Event{int(_buf[0]), 0, nil}
	}
	r, rsz := utf8.DecodeRune(_buf)
	if r == utf8.RuneError {
		return Event{ESC, 0, nil}
	}
	sz = rsz
	return Event{Rune, r, nil}
}

func Move(y int, x int) {
	C.move(C.int(y), C.int(x))
}

func MoveAndClear(y int, x int) {
	Move(y, x)
	C.clrtoeol()
}

func Print(text string) {
	C.addstr(C.CString(text))
}

func CPrint(pair int, bold bool, text string) {
	attr := _color(pair, bold)
	C.attron(attr)
	Print(text)
	C.attroff(attr)
}

func Clear() {
	C.clear()
}

func Endwin() {
	C.endwin()
}

func Refresh() {
	C.refresh()
}

func PairFor(fg int, bg int) int {
	key := (fg << 8) + bg
	if found, prs := _colorMap[key]; prs {
		return found
	}

	id := len(_colorMap) + ColUser
	C.init_pair(C.short(id), C.short(fg), C.short(bg))
	_colorMap[key] = id
	return id
}
<|endoftext|>


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

package backup_test

import (
	"errors"
	"github.com/jacobsa/comeback/backup"
	"github.com/jacobsa/comeback/backup/mock"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/blob/mock"
	"github.com/jacobsa/comeback/fs/mock"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestRegisterDirsTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DirectorySaverTest struct {
	blobStore mock_blob.MockStore
	fileSystem mock_fs.MockFileSystem
	fileSaver mock_backup.MockFileSaver
	wrapped mock_backup.MockDirectorySaver

	dirSaver backup.DirectorySaver

	dirpath string
	score blob.Score
	err error
}

func init() { RegisterTestSuite(&DirectorySaverTest{}) }

func (t *DirectorySaverTest) SetUp(i *TestInfo) {
	t.blobStore = mock_blob.NewMockStore(i.MockController, "blobStore")
	t.fileSystem = mock_fs.NewMockFileSystem(i.MockController, "fileSystem")
	t.fileSaver = mock_backup.NewMockFileSaver(i.MockController, "fileSaver")
	t.wrapped = mock_backup.NewMockDirectorySaver(i.MockController, "wrapped")

	t.dirSaver, _ = backup.NewDirectorySaver(
		t.blobStore,
		t.fileSystem,
		t.fileSaver,
		t.wrapped,
	)
}

func (t *DirectorySaverTest) callSaver() {
	t.score, t.err = t.dirSaver.Save(t.dirpath)
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *DirectorySaverTest) CallsReadDir() {
	t.dirpath = "taco"

	// ReadDir
	ExpectCall(t.fileSystem, "ReadDir")("taco").
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.callSaver()
}

func (t *DirectorySaverTest) ReadDirReturnsError() {
	// ReadDir
	ExpectCall(t.fileSystem, "ReadDir")(Any()).
		WillOnce(oglemock.Return(nil, errors.New("taco")))

	// Call
	t.callSaver()

	ExpectThat(t.err, Error(HasSubstr("Listing")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *DirectorySaverTest) NoEntriesInDirectory() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) CallsFileSaverForFiles() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) FileSaverReturnsErrorForOneFile() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) CallsDirSaverForDirs() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) DirSaverReturnsErrorForOneDir() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) OneTypeIsUnsupported() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) EverythingSucceeds() {
	ExpectEq("TODO", "")
}
<commit_msg>DirectorySaverTest.NoEntriesInDirectory<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package backup_test

import (
	"errors"
	"github.com/jacobsa/comeback/backup"
	"github.com/jacobsa/comeback/backup/mock"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/blob/mock"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/fs/mock"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestRegisterDirsTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DirectorySaverTest struct {
	blobStore mock_blob.MockStore
	fileSystem mock_fs.MockFileSystem
	fileSaver mock_backup.MockFileSaver
	wrapped mock_backup.MockDirectorySaver

	dirSaver backup.DirectorySaver

	dirpath string
	score blob.Score
	err error
}

func init() { RegisterTestSuite(&DirectorySaverTest{}) }

func (t *DirectorySaverTest) SetUp(i *TestInfo) {
	t.blobStore = mock_blob.NewMockStore(i.MockController, "blobStore")
	t.fileSystem = mock_fs.NewMockFileSystem(i.MockController, "fileSystem")
	t.fileSaver = mock_backup.NewMockFileSaver(i.MockController, "fileSaver")
	t.wrapped = mock_backup.NewMockDirectorySaver(i.MockController, "wrapped")

	t.dirSaver, _ = backup.NewDirectorySaver(
		t.blobStore,
		t.fileSystem,
		t.fileSaver,
		t.wrapped,
	)
}

func (t *DirectorySaverTest) callSaver() {
	t.score, t.err = t.dirSaver.Save(t.dirpath)
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *DirectorySaverTest) CallsReadDir() {
	t.dirpath = "taco"

	// ReadDir
	ExpectCall(t.fileSystem, "ReadDir")("taco").
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.callSaver()
}

func (t *DirectorySaverTest) ReadDirReturnsError() {
	// ReadDir
	ExpectCall(t.fileSystem, "ReadDir")(Any()).
		WillOnce(oglemock.Return(nil, errors.New("taco")))

	// Call
	t.callSaver()

	ExpectThat(t.err, Error(HasSubstr("Listing")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *DirectorySaverTest) NoEntriesInDirectory() {
	// ReadDir
	ExpectCall(t.fileSystem, "ReadDir")(Any()).
		WillOnce(oglemock.Return([]*fs.DirectoryEntry{}, nil))

	// Blob store
	ExpectCall(t.blobStore, "Store")(DeepEquals([]byte{})).
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.callSaver()
}

func (t *DirectorySaverTest) CallsFileSaverForFiles() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) FileSaverReturnsErrorForOneFile() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) CallsDirSaverForDirs() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) DirSaverReturnsErrorForOneDir() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) OneTypeIsUnsupported() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) CallsBlobStore() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) BlobStoreReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectorySaverTest) BlobStoreSucceeds() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/realglobe-Inc/edo/util"
	"github.com/realglobe-Inc/go-lib-rg/erro"
	"github.com/realglobe-Inc/go-lib-rg/file"
	"github.com/realglobe-Inc/go-lib-rg/rglog/level"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type parameters struct {
	// 画面表示ログ。
	consLv level.Level

	// 追加ログ。
	logType string
	logLv   level.Level

	// ファイルログ。
	logPath string

	// fluentd ログ。
	fluAddr string
	fluTag  string

	// サービス検索。
	taExpType string

	// ファイルベースサービス検索。
	taExpPath string

	// Web ベースサービス検索。
	taExpAddr string

	// mongo サービス検索。
	taExpUrl  string
	taExpDb   string
	taExpColl string

	// 公開鍵レジストリ。
	taKeyRegType string

	// ファイルベース公開鍵レジストリ。
	taKeyRegPath string

	// Web ベース公開鍵レジストリ。
	taKeyRegAddr string

	// mongo 公開鍵レジストリ。
	taKeyRegUrl  string
	taKeyRegDb   string
	taKeyRegColl string

	// ユーザー名索引。
	usrNameIdxType string

	// ファイルベースユーザー名索引。
	usrNameIdxPath string

	// mongo ユーザー名索引。
	usrNameIdxUrl  string
	usrNameIdxDb   string
	usrNameIdxColl string

	// ユーザー属性レジストリ。
	usrAttrRegType string

	// ファイルベースユーザー属性レジストリ。
	usrAttrRegPath string

	// mongo ユーザー属性レジストリ。
	usrAttrRegUrl  string
	usrAttrRegDb   string
	usrAttrRegColl string

	// セッション管理。
	sessContType string

	// ファイルベースセッション管理。
	sessContPath string

	// mongo セッション管理。
	sessContUrl  string
	sessContDb   string
	sessContColl string

	// アクセストークン発行用コード管理。
	codeContType string

	// ファイルベースアクセストークン発行用コード管理。
	codeContPath string

	// mongo アクセストークン発行用コード管理。
	codeContUrl  string
	codeContDb   string
	codeContColl string

	// アクセストークン管理。
	accTokenContType string

	// ファイルベースアクセストークン管理。
	accTokenContPath string

	// mongo アクセストークン管理。
	accTokenContUrl  string
	accTokenContDb   string
	accTokenContColl string

	// ソケット。
	socType string

	// UNIX ソケット。
	socPath string

	// TCP ソケット。
	socPort int

	// プロトコル。
	protType string

	// 無通信での認証済みセッションの有効期間。
	maxSessExpiDur time.Duration // デフォルトかつ最大。

	// アクセストークン発行用コードの有効期間。
	codeExpiDur time.Duration

	// アクセストークンの有効期間。
	accTokenExpiDur    time.Duration // デフォルト。
	maxAccTokenExpiDur time.Duration
}

func parseParameters(args ...string) (param *parameters, err error) {

	const label = "edo-id-provider"

	flags := util.NewFlagSet(label+" parameters", flag.ExitOnError)
	flags.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage:")
		fmt.Fprintln(os.Stderr, "  "+args[0]+" [{FLAG}...]")
		fmt.Fprintln(os.Stderr, "FLAG:")
		flags.PrintDefaults()
	}

	param = &parameters{}

	flags.Var(level.Var(&param.consLv, level.INFO), "consLv", "Console log level.")
	flags.StringVar(&param.logType, "logType", "", "Extra log type.")
	flags.Var(level.Var(&param.logLv, level.ALL), "logLv", "Extra log level.")
	flags.StringVar(&param.logPath, "logPath", filepath.Join(filepath.Dir(os.Args[0]), "log", label+".log"), "File log path.")
	flags.StringVar(&param.fluAddr, "fluAddr", "localhost:24224", "fluentd address.")
	flags.StringVar(&param.fluTag, "fluTag", "edo."+label, "fluentd tag.")

	flags.StringVar(&param.taExpType, "taExpType", "web", "TA explorer type.")
	flags.StringVar(&param.taExpPath, "taExpPath", filepath.Join(filepath.Dir(os.Args[0]), "ta_uris"), "TA explorer directory.")
	flags.StringVar(&param.taExpAddr, "taExpAddr", "http://localhost:16034", "TA explorer address.")
	flags.StringVar(&param.taExpUrl, "taExpUrl", "localhost", "TA explorer address.")
	flags.StringVar(&param.taExpDb, "taExpDb", "edo", "TA explorer database name.")
	flags.StringVar(&param.taExpColl, "taExpColl", "ta_uris", "TA explorer collection name.")

	flags.StringVar(&param.taKeyRegType, "taKeyRegType", "web", "TA key provider type.")
	flags.StringVar(&param.taKeyRegPath, "taKeyRegPath", filepath.Join(filepath.Dir(os.Args[0]), "public_keys"), "TA key provider directory.")
	flags.StringVar(&param.taKeyRegAddr, "taKeyRegAddr", "http://localhost:16033", "TA key provider address.")
	flags.StringVar(&param.taKeyRegUrl, "taKeyRegUrl", "localhost", "TA key provider address.")
	flags.StringVar(&param.taKeyRegDb, "taKeyRegDb", "edo", "TA key provider database name.")
	flags.StringVar(&param.taKeyRegColl, "taKeyRegColl", "public_keys", "TA key provider collection name.")

	flags.StringVar(&param.usrNameIdxType, "usrNameIdxType", "mongo", "Username index type.")
	flags.StringVar(&param.usrNameIdxPath, "usrNameIdxPath", filepath.Join(filepath.Dir(os.Args[0]), "user_ids"), "Username index directory.")
	flags.StringVar(&param.usrNameIdxUrl, "usrNameIdxUrl", "localhost", "Username index address.")
	flags.StringVar(&param.usrNameIdxDb, "usrNameIdxDb", "edo", "Username index database name.")
	flags.StringVar(&param.usrNameIdxColl, "usrNameIdxColl", "user_ids", "Username index collection name.")

	flags.StringVar(&param.usrAttrRegType, "usrAttrRegType", "mongo", "User attribute registry type.")
	flags.StringVar(&param.usrAttrRegPath, "usrAttrRegPath", filepath.Join(filepath.Dir(os.Args[0]), "user_attributes"), "User attribute registry directory.")
	flags.StringVar(&param.usrAttrRegUrl, "usrAttrRegUrl", "localhost", "User attribute registry address.")
	flags.StringVar(&param.usrAttrRegDb, "usrAttrRegDb", "edo", "User attribute registry database name.")
	flags.StringVar(&param.usrAttrRegColl, "usrAttrRegColl", "user_attributes", "User attribute registry collection name.")

	flags.StringVar(&param.sessContType, "sessContType", "mongo", "Session container lister type.")
	flags.StringVar(&param.sessContPath, "sessContPath", filepath.Join(filepath.Dir(os.Args[0]), "sessions"), "Session container lister directory.")
	flags.StringVar(&param.sessContUrl, "sessContUrl", "localhost", "Session container lister address.")
	flags.StringVar(&param.sessContDb, "sessContDb", "edo", "Session container lister database name.")
	flags.StringVar(&param.sessContColl, "sessContColl", "sessions", "Session container lister collection name.")

	flags.StringVar(&param.codeContType, "codeContType", "mongo", "Code container lister type.")
	flags.StringVar(&param.codeContPath, "codeContPath", filepath.Join(filepath.Dir(os.Args[0]), "access_codes"), "Code container lister directory.")
	flags.StringVar(&param.codeContUrl, "codeContUrl", "localhost", "Code container lister address.")
	flags.StringVar(&param.codeContDb, "codeContDb", "edo", "Code container lister database name.")
	flags.StringVar(&param.codeContColl, "codeContColl", "access_codes", "Code container lister collection name.")

	flags.StringVar(&param.accTokenContType, "accTokenContType", "mongo", "Access token container lister type.")
	flags.StringVar(&param.accTokenContPath, "accTokenContPath", filepath.Join(filepath.Dir(os.Args[0]), "access_tokens"), "Access token container lister directory.")
	flags.StringVar(&param.accTokenContUrl, "accTokenContUrl", "localhost", "Access token container lister address.")
	flags.StringVar(&param.accTokenContDb, "accTokenContDb", "edo", "Access token container lister database name.")
	flags.StringVar(&param.accTokenContColl, "accTokenContColl", "access_tokens", "Access token container lister collection name.")

	flags.StringVar(&param.socType, "socType", "tcp", "Socket type.")
	flags.StringVar(&param.socPath, "socPath", filepath.Join(filepath.Dir(os.Args[0]), "run", label+".soc"), "UNIX socket path.")
	flags.IntVar(&param.socPort, "socPort", 16040, "TCP socket port.")

	flags.StringVar(&param.protType, "protType", "http", "Protocol type.")

	flags.DurationVar(&param.maxSessExpiDur, "maxSessExpiDur", 24*time.Hour, "Max session expiration duration.")
	flags.DurationVar(&param.codeExpiDur, "codeExpiDur", 10*time.Minute, "Code expiration duration.")
	flags.DurationVar(&param.accTokenExpiDur, "accTokenExpiDur", 24*time.Hour, "Default access token expiration duration.")
	flags.DurationVar(&param.maxAccTokenExpiDur, "maxAccTokenExpiDur", 30*24*time.Hour, "Max access token expiration duration.")

	var config string
	flags.StringVar(&config, "f", "", "Config file path.")

	// 実行引数を読んで、設定ファイルを指定させてから、
	// 設定ファイルを読んで、また実行引数を読む。
	flags.Parse(args[1:])
	if config != "" {
		if exist, err := file.IsExist(config); err != nil {
			return nil, erro.Wrap(err)
		} else if !exist {
			log.Warn("Config file " + config + " is not exist.")
		} else {
			buff, err := ioutil.ReadFile(config)
			if err != nil {
				return nil, erro.Wrap(err)
			}
			flags.CompleteParse(strings.Fields(string(buff)))
		}
	}
	flags.Parse(args[1:])

	if l := len(flags.Args()); l > 0 {
		log.Warn("Ignore extra parameters ", flags.Args(), ".")
	}

	return param, nil
}
<commit_msg>go-lib-rg/file に依存しなくした<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/realglobe-Inc/edo/util"
	"github.com/realglobe-Inc/go-lib-rg/erro"
	"github.com/realglobe-Inc/go-lib-rg/rglog/level"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type parameters struct {
	// 画面表示ログ。
	consLv level.Level

	// 追加ログ。
	logType string
	logLv   level.Level

	// ファイルログ。
	logPath string

	// fluentd ログ。
	fluAddr string
	fluTag  string

	// サービス検索。
	taExpType string

	// ファイルベースサービス検索。
	taExpPath string

	// Web ベースサービス検索。
	taExpAddr string

	// mongo サービス検索。
	taExpUrl  string
	taExpDb   string
	taExpColl string

	// 公開鍵レジストリ。
	taKeyRegType string

	// ファイルベース公開鍵レジストリ。
	taKeyRegPath string

	// Web ベース公開鍵レジストリ。
	taKeyRegAddr string

	// mongo 公開鍵レジストリ。
	taKeyRegUrl  string
	taKeyRegDb   string
	taKeyRegColl string

	// ユーザー名索引。
	usrNameIdxType string

	// ファイルベースユーザー名索引。
	usrNameIdxPath string

	// mongo ユーザー名索引。
	usrNameIdxUrl  string
	usrNameIdxDb   string
	usrNameIdxColl string

	// ユーザー属性レジストリ。
	usrAttrRegType string

	// ファイルベースユーザー属性レジストリ。
	usrAttrRegPath string

	// mongo ユーザー属性レジストリ。
	usrAttrRegUrl  string
	usrAttrRegDb   string
	usrAttrRegColl string

	// セッション管理。
	sessContType string

	// ファイルベースセッション管理。
	sessContPath string

	// mongo セッション管理。
	sessContUrl  string
	sessContDb   string
	sessContColl string

	// アクセストークン発行用コード管理。
	codeContType string

	// ファイルベースアクセストークン発行用コード管理。
	codeContPath string

	// mongo アクセストークン発行用コード管理。
	codeContUrl  string
	codeContDb   string
	codeContColl string

	// アクセストークン管理。
	accTokenContType string

	// ファイルベースアクセストークン管理。
	accTokenContPath string

	// mongo アクセストークン管理。
	accTokenContUrl  string
	accTokenContDb   string
	accTokenContColl string

	// ソケット。
	socType string

	// UNIX ソケット。
	socPath string

	// TCP ソケット。
	socPort int

	// プロトコル。
	protType string

	// 無通信での認証済みセッションの有効期間。
	maxSessExpiDur time.Duration // デフォルトかつ最大。

	// アクセストークン発行用コードの有効期間。
	codeExpiDur time.Duration

	// アクセストークンの有効期間。
	accTokenExpiDur    time.Duration // デフォルト。
	maxAccTokenExpiDur time.Duration
}

func parseParameters(args ...string) (param *parameters, err error) {

	const label = "edo-id-provider"

	flags := util.NewFlagSet(label+" parameters", flag.ExitOnError)
	flags.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage:")
		fmt.Fprintln(os.Stderr, "  "+args[0]+" [{FLAG}...]")
		fmt.Fprintln(os.Stderr, "FLAG:")
		flags.PrintDefaults()
	}

	param = &parameters{}

	flags.Var(level.Var(&param.consLv, level.INFO), "consLv", "Console log level.")
	flags.StringVar(&param.logType, "logType", "", "Extra log type.")
	flags.Var(level.Var(&param.logLv, level.ALL), "logLv", "Extra log level.")
	flags.StringVar(&param.logPath, "logPath", filepath.Join(filepath.Dir(os.Args[0]), "log", label+".log"), "File log path.")
	flags.StringVar(&param.fluAddr, "fluAddr", "localhost:24224", "fluentd address.")
	flags.StringVar(&param.fluTag, "fluTag", "edo."+label, "fluentd tag.")

	flags.StringVar(&param.taExpType, "taExpType", "web", "TA explorer type.")
	flags.StringVar(&param.taExpPath, "taExpPath", filepath.Join(filepath.Dir(os.Args[0]), "ta_uris"), "TA explorer directory.")
	flags.StringVar(&param.taExpAddr, "taExpAddr", "http://localhost:16034", "TA explorer address.")
	flags.StringVar(&param.taExpUrl, "taExpUrl", "localhost", "TA explorer address.")
	flags.StringVar(&param.taExpDb, "taExpDb", "edo", "TA explorer database name.")
	flags.StringVar(&param.taExpColl, "taExpColl", "ta_uris", "TA explorer collection name.")

	flags.StringVar(&param.taKeyRegType, "taKeyRegType", "web", "TA key provider type.")
	flags.StringVar(&param.taKeyRegPath, "taKeyRegPath", filepath.Join(filepath.Dir(os.Args[0]), "public_keys"), "TA key provider directory.")
	flags.StringVar(&param.taKeyRegAddr, "taKeyRegAddr", "http://localhost:16033", "TA key provider address.")
	flags.StringVar(&param.taKeyRegUrl, "taKeyRegUrl", "localhost", "TA key provider address.")
	flags.StringVar(&param.taKeyRegDb, "taKeyRegDb", "edo", "TA key provider database name.")
	flags.StringVar(&param.taKeyRegColl, "taKeyRegColl", "public_keys", "TA key provider collection name.")

	flags.StringVar(&param.usrNameIdxType, "usrNameIdxType", "mongo", "Username index type.")
	flags.StringVar(&param.usrNameIdxPath, "usrNameIdxPath", filepath.Join(filepath.Dir(os.Args[0]), "user_ids"), "Username index directory.")
	flags.StringVar(&param.usrNameIdxUrl, "usrNameIdxUrl", "localhost", "Username index address.")
	flags.StringVar(&param.usrNameIdxDb, "usrNameIdxDb", "edo", "Username index database name.")
	flags.StringVar(&param.usrNameIdxColl, "usrNameIdxColl", "user_ids", "Username index collection name.")

	flags.StringVar(&param.usrAttrRegType, "usrAttrRegType", "mongo", "User attribute registry type.")
	flags.StringVar(&param.usrAttrRegPath, "usrAttrRegPath", filepath.Join(filepath.Dir(os.Args[0]), "user_attributes"), "User attribute registry directory.")
	flags.StringVar(&param.usrAttrRegUrl, "usrAttrRegUrl", "localhost", "User attribute registry address.")
	flags.StringVar(&param.usrAttrRegDb, "usrAttrRegDb", "edo", "User attribute registry database name.")
	flags.StringVar(&param.usrAttrRegColl, "usrAttrRegColl", "user_attributes", "User attribute registry collection name.")

	flags.StringVar(&param.sessContType, "sessContType", "mongo", "Session container lister type.")
	flags.StringVar(&param.sessContPath, "sessContPath", filepath.Join(filepath.Dir(os.Args[0]), "sessions"), "Session container lister directory.")
	flags.StringVar(&param.sessContUrl, "sessContUrl", "localhost", "Session container lister address.")
	flags.StringVar(&param.sessContDb, "sessContDb", "edo", "Session container lister database name.")
	flags.StringVar(&param.sessContColl, "sessContColl", "sessions", "Session container lister collection name.")

	flags.StringVar(&param.codeContType, "codeContType", "mongo", "Code container lister type.")
	flags.StringVar(&param.codeContPath, "codeContPath", filepath.Join(filepath.Dir(os.Args[0]), "access_codes"), "Code container lister directory.")
	flags.StringVar(&param.codeContUrl, "codeContUrl", "localhost", "Code container lister address.")
	flags.StringVar(&param.codeContDb, "codeContDb", "edo", "Code container lister database name.")
	flags.StringVar(&param.codeContColl, "codeContColl", "access_codes", "Code container lister collection name.")

	flags.StringVar(&param.accTokenContType, "accTokenContType", "mongo", "Access token container lister type.")
	flags.StringVar(&param.accTokenContPath, "accTokenContPath", filepath.Join(filepath.Dir(os.Args[0]), "access_tokens"), "Access token container lister directory.")
	flags.StringVar(&param.accTokenContUrl, "accTokenContUrl", "localhost", "Access token container lister address.")
	flags.StringVar(&param.accTokenContDb, "accTokenContDb", "edo", "Access token container lister database name.")
	flags.StringVar(&param.accTokenContColl, "accTokenContColl", "access_tokens", "Access token container lister collection name.")

	flags.StringVar(&param.socType, "socType", "tcp", "Socket type.")
	flags.StringVar(&param.socPath, "socPath", filepath.Join(filepath.Dir(os.Args[0]), "run", label+".soc"), "UNIX socket path.")
	flags.IntVar(&param.socPort, "socPort", 16040, "TCP socket port.")

	flags.StringVar(&param.protType, "protType", "http", "Protocol type.")

	flags.DurationVar(&param.maxSessExpiDur, "maxSessExpiDur", 24*time.Hour, "Max session expiration duration.")
	flags.DurationVar(&param.codeExpiDur, "codeExpiDur", 10*time.Minute, "Code expiration duration.")
	flags.DurationVar(&param.accTokenExpiDur, "accTokenExpiDur", 24*time.Hour, "Default access token expiration duration.")
	flags.DurationVar(&param.maxAccTokenExpiDur, "maxAccTokenExpiDur", 30*24*time.Hour, "Max access token expiration duration.")

	var config string
	flags.StringVar(&config, "f", "", "Config file path.")

	// 実行引数を読んで、設定ファイルを指定させてから、
	// 設定ファイルを読んで、また実行引数を読む。
	flags.Parse(args[1:])
	if config != "" {
		if buff, err := ioutil.ReadFile(config); err != nil {
			if !os.IsNotExist(err) {
				return nil, erro.Wrap(err)
			}
			log.Warn("Config file " + config + " is not exist.")
		} else {
			flags.CompleteParse(strings.Fields(string(buff)))
		}
	}
	flags.Parse(args[1:])

	if l := len(flags.Args()); l > 0 {
		log.Warn("Ignore extra parameters ", flags.Args(), ".")
	}

	return param, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2018-2019 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package txscript

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"testing"

	"github.com/decred/dcrd/wire"
)

var (
	// manyInputsBenchTx is a transaction that contains a lot of inputs which is
	// useful for benchmarking signature hash calculation.
	manyInputsBenchTx wire.MsgTx

	// A mock previous output script to use in the signing benchmark.
	prevOutScript = hexToBytes("a914f5916158e3e2c4551c1796708db8367207ed13bb87")
)

func init() {
	// tx 620f57c92cf05a7f7e7f7d28255d5f7089437bc48e34dcfebf7751d08b7fb8f5
	txHex, err := ioutil.ReadFile("data/many_inputs_tx.hex")
	if err != nil {
		panic(fmt.Sprintf("unable to read benchmark tx file: %v", err))
	}

	txBytes := hexToBytes(string(txHex))
	err = manyInputsBenchTx.Deserialize(bytes.NewReader(txBytes))
	if err != nil {
		panic(err)
	}
}

// BenchmarkCalcSigHash benchmarks how long it takes to calculate the signature
// hashes for all inputs of a transaction with many inputs.
func BenchmarkCalcSigHash(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for j := 0; j < len(manyInputsBenchTx.TxIn); j++ {
			_, err := CalcSignatureHash(prevOutScript, SigHashAll,
				&manyInputsBenchTx, j, nil)
			if err != nil {
				b.Fatalf("failed to calc signature hash: %v", err)
			}
		}
	}
}

// genComplexScript returns a script comprised of half as many opcodes as the
// maximum allowed followed by as many max size data pushes fit without
// exceeding the max allowed script size.
func genComplexScript() ([]byte, error) {
	var scriptLen int
	builder := NewScriptBuilder()
	for i := 0; i < MaxOpsPerScript/2; i++ {
		builder.AddOp(OP_TRUE)
		scriptLen++
	}
	maxData := bytes.Repeat([]byte{0x02}, MaxScriptElementSize)
	for i := 0; i < (MaxScriptSize-scriptLen)/MaxScriptElementSize; i++ {
		builder.AddData(maxData)
	}
	return builder.Script()
}

// BenchmarkScriptParsing benchmarks how long it takes to parse a very large
// script.
func BenchmarkScriptParsing(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	const scriptVersion = 0
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tokenizer := MakeScriptTokenizer(scriptVersion, script)
		for tokenizer.Next() {
			_ = tokenizer.Opcode()
			_ = tokenizer.Data()
			_ = tokenizer.ByteIndex()
		}
		if err := tokenizer.Err(); err != nil {
			b.Fatalf("failed to parse script: %v", err)
		}
	}
}

// BenchmarkDisasmString benchmarks how long it takes to disassemble a very
// large script.
func BenchmarkDisasmString(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := DisasmString(script)
		if err != nil {
			b.Fatalf("failed to disasm script: %v", err)
		}
	}
}

// BenchmarkIsPayToScriptHash benchmarks how long it takes IsPayToScriptHash to
// analyze a very large script.
func BenchmarkIsPayToScriptHash(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = IsPayToScriptHash(script)
	}
}
<commit_msg>txscript: Add benchmarks for IsMutlsigScript.<commit_after>// Copyright (c) 2018-2019 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package txscript

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"testing"

	"github.com/decred/dcrd/wire"
)

var (
	// manyInputsBenchTx is a transaction that contains a lot of inputs which is
	// useful for benchmarking signature hash calculation.
	manyInputsBenchTx wire.MsgTx

	// A mock previous output script to use in the signing benchmark.
	prevOutScript = hexToBytes("a914f5916158e3e2c4551c1796708db8367207ed13bb87")
)

func init() {
	// tx 620f57c92cf05a7f7e7f7d28255d5f7089437bc48e34dcfebf7751d08b7fb8f5
	txHex, err := ioutil.ReadFile("data/many_inputs_tx.hex")
	if err != nil {
		panic(fmt.Sprintf("unable to read benchmark tx file: %v", err))
	}

	txBytes := hexToBytes(string(txHex))
	err = manyInputsBenchTx.Deserialize(bytes.NewReader(txBytes))
	if err != nil {
		panic(err)
	}
}

// BenchmarkCalcSigHash benchmarks how long it takes to calculate the signature
// hashes for all inputs of a transaction with many inputs.
func BenchmarkCalcSigHash(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for j := 0; j < len(manyInputsBenchTx.TxIn); j++ {
			_, err := CalcSignatureHash(prevOutScript, SigHashAll,
				&manyInputsBenchTx, j, nil)
			if err != nil {
				b.Fatalf("failed to calc signature hash: %v", err)
			}
		}
	}
}

// genComplexScript returns a script comprised of half as many opcodes as the
// maximum allowed followed by as many max size data pushes fit without
// exceeding the max allowed script size.
func genComplexScript() ([]byte, error) {
	var scriptLen int
	builder := NewScriptBuilder()
	for i := 0; i < MaxOpsPerScript/2; i++ {
		builder.AddOp(OP_TRUE)
		scriptLen++
	}
	maxData := bytes.Repeat([]byte{0x02}, MaxScriptElementSize)
	for i := 0; i < (MaxScriptSize-scriptLen)/MaxScriptElementSize; i++ {
		builder.AddData(maxData)
	}
	return builder.Script()
}

// BenchmarkScriptParsing benchmarks how long it takes to parse a very large
// script.
func BenchmarkScriptParsing(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	const scriptVersion = 0
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tokenizer := MakeScriptTokenizer(scriptVersion, script)
		for tokenizer.Next() {
			_ = tokenizer.Opcode()
			_ = tokenizer.Data()
			_ = tokenizer.ByteIndex()
		}
		if err := tokenizer.Err(); err != nil {
			b.Fatalf("failed to parse script: %v", err)
		}
	}
}

// BenchmarkDisasmString benchmarks how long it takes to disassemble a very
// large script.
func BenchmarkDisasmString(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := DisasmString(script)
		if err != nil {
			b.Fatalf("failed to disasm script: %v", err)
		}
	}
}

// BenchmarkIsPayToScriptHash benchmarks how long it takes IsPayToScriptHash to
// analyze a very large script.
func BenchmarkIsPayToScriptHash(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = IsPayToScriptHash(script)
	}
}

// BenchmarkIsMultisigScriptLarge benchmarks how long it takes IsMultisigScript
// to analyze a very large script.
func BenchmarkIsMultisigScriptLarge(b *testing.B) {
	script, err := genComplexScript()
	if err != nil {
		b.Fatalf("failed to create benchmark script: %v", err)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		isMultisig, err := IsMultisigScript(script)
		if err != nil {
			b.Fatalf("unexpected err: %v", err)
		}
		if isMultisig {
			b.Fatalf("script should NOT be reported as mutisig script")
		}
	}
}

// BenchmarkIsMultisigScript benchmarks how long it takes IsMultisigScript to
// analyze a 1-of-2 multisig public key script.
func BenchmarkIsMultisigScript(b *testing.B) {
	multisigShortForm := "1 " +
		"DATA_33 " +
		"0x030478aaaa2be30772f1e69e581610f1840b3cf2fe7228ee0281cd599e5746f81e " +
		"DATA_33 " +
		"0x0284f4d078b236a9ff91661f8ffbe012737cd3507566f30fd97d25f2b23539f3cd " +
		"2 CHECKMULTISIG"
	pkScript := mustParseShortForm(multisigShortForm)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		isMultisig, err := IsMultisigScript(pkScript)
		if err != nil {
			b.Fatalf("unexpected err: %v", err)
		}
		if !isMultisig {
			b.Fatalf("script should be reported as a mutisig script")
		}
	}
}
<|endoftext|>


<commit_before>package kala

import (
	"fmt"
	"math/big"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

var bigId *big.Int

func TestMintBigflakeId(t *testing.T) {

	mac := "80:36:bc:db:64:16"
	workerId, err := MacAddressToWorkerId(mac)
	if err != nil {
		t.Fail()
	}

	bf := &Bigflake{
		lastTimestamp: timeToMsInt64(time.Now()),

		workerIdBits: defaultBigflakeWorkerIdBits,
		sequenceBits: defaultBigflakeSequenceBits,

		workerId: workerId,
		sequence: 0,
		epoch:    0,
	}

	start := time.Now()

	var id *big.Int
	for i := 0; i < 10; i++ {
		id, _ = bf.Mint()
		// t.Log(id.String())
		fmt.Printf("%s\n", id.String())
		fmt.Printf("%0128b\n", id)
		// assert.NoError(t, err)
	}

	bigId = id

	fmt.Println("elapsed: ", time.Since(start))

}

func TestBigflakeSnowflakeMintCompatibility(t *testing.T) {
	testCases := []struct {
		lastTs   int64
		workerId int64
		sequence int64
		id       uint64
	}{
		{1397666977000, 0, 0, 5862240192299008000},     // Plain bit shift 22
		{2344466898000, 0, 0, 9833406888148992000},     // Plain bit shift 22
		{1397666977000, 10, 0, 5862240192299048960},    // Worker 10
		{2344466898000, 10, 0, 9833406888149032960},    // Worker 10
		{1397666977000, 1023, 0, 5862240192303198208},  // Worker 1023
		{2344466898000, 1023, 0, 9833406888153182208},  // Worker 1023
		{1397666977000, 10, 123, 5862240192299049083},  // Worker 10 & Sequence 123
		{2344466898000, 10, 1230, 9833406888149034190}, // Worker 10 & Sequence 1230
		{1397666977000, 10, 2356, 5862240192299051316}, // Worker 10 & Sequence 2356
		{2344466898000, 10, 4090, 9833406888149037050}, // Worker 10 & Sequence 4090
	}

	// Test that the bigflake minter generates snowflake compatible IDs
	// when provided with the same test cases
	for _, tc := range testCases {
		bf := &Bigflake{}
		id := bf.mintId(tc.lastTs, tc.workerId, tc.sequence, 10, 12)

		fmt.Println("uint:", id.Uint64())
		fmt.Printf("bin : %0128b\n", id)

		assert.Equal(t, uint64(tc.id), id.Uint64(), fmt.Sprintf("IDs should match. Provided: '%s', Returned: '%s' ", tc.id, id))
	}
}

func BenchmarkMintBigflakeId(b *testing.B) {
	var id *big.Int
	var lastTs, workerId, sequenceId int64

	// Setup
	lastTs, workerId, sequenceId = 1397666977000, 10, 2356
	bf := &Bigflake{}

	// Zoom!
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		id = bf.mintId(lastTs, workerId, sequenceId, 10, 12)
	}

	// always store the result to a package level variable
	// so the compiler cannot eliminate the Benchmark itself.
	bigId = id
}
<commit_msg>Fix passing id in test<commit_after>package kala

import (
	"fmt"
	"math/big"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

var bigId *big.Int

func TestMintBigflakeId(t *testing.T) {

	mac := "80:36:bc:db:64:16"
	workerId, err := MacAddressToWorkerId(mac)
	if err != nil {
		t.Fail()
	}

	bf := &Bigflake{
		lastTimestamp: timeToMsInt64(time.Now()),

		workerIdBits: defaultBigflakeWorkerIdBits,
		sequenceBits: defaultBigflakeSequenceBits,

		workerId: int64(workerId),
		sequence: 0,
		epoch:    0,
	}

	start := time.Now()

	var id *big.Int
	for i := 0; i < 10; i++ {
		id, _ = bf.Mint()
		// t.Log(id.String())
		fmt.Printf("%s\n", id.String())
		fmt.Printf("%0128b\n", id)
		// assert.NoError(t, err)
	}

	bigId = id

	fmt.Println("elapsed: ", time.Since(start))

}

func TestBigflakeSnowflakeMintCompatibility(t *testing.T) {
	testCases := []struct {
		lastTs   int64
		workerId int64
		sequence int64
		id       uint64
	}{
		{1397666977000, 0, 0, 5862240192299008000},     // Plain bit shift 22
		{2344466898000, 0, 0, 9833406888148992000},     // Plain bit shift 22
		{1397666977000, 10, 0, 5862240192299048960},    // Worker 10
		{2344466898000, 10, 0, 9833406888149032960},    // Worker 10
		{1397666977000, 1023, 0, 5862240192303198208},  // Worker 1023
		{2344466898000, 1023, 0, 9833406888153182208},  // Worker 1023
		{1397666977000, 10, 123, 5862240192299049083},  // Worker 10 & Sequence 123
		{2344466898000, 10, 1230, 9833406888149034190}, // Worker 10 & Sequence 1230
		{1397666977000, 10, 2356, 5862240192299051316}, // Worker 10 & Sequence 2356
		{2344466898000, 10, 4090, 9833406888149037050}, // Worker 10 & Sequence 4090
	}

	// Test that the bigflake minter generates snowflake compatible IDs
	// when provided with the same test cases
	for _, tc := range testCases {
		bf := &Bigflake{}
		id := bf.mintId(tc.lastTs, tc.workerId, tc.sequence, 10, 12)

		fmt.Println("uint:", id.Uint64())
		fmt.Printf("bin : %0128b\n", id)

		assert.Equal(t, uint64(tc.id), id.Uint64(), fmt.Sprintf("IDs should match. Provided: '%s', Returned: '%s' ", tc.id, id))
	}
}

func BenchmarkMintBigflakeId(b *testing.B) {
	var id *big.Int
	var lastTs, workerId, sequenceId int64

	// Setup
	lastTs, workerId, sequenceId = 1397666977000, 10, 2356
	bf := &Bigflake{}

	// Zoom!
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		id = bf.mintId(lastTs, workerId, sequenceId, 10, 12)
	}

	// always store the result to a package level variable
	// so the compiler cannot eliminate the Benchmark itself.
	bigId = id
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Fission Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"net/http"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/satori/go.uuid"
	"github.com/urfave/cli"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"github.com/fission/fission"
	"github.com/fission/fission/crd"
)

// returns one of http.Method*
func getMethod(method string) string {
	switch strings.ToUpper(method) {
	case "GET":
		return http.MethodGet
	case "HEAD":
		return http.MethodHead
	case "POST":
		return http.MethodPost
	case "PUT":
		return http.MethodPut
	case "PATCH":
		return http.MethodPatch
	case "DELETE":
		return http.MethodDelete
	case "CONNECT":
		return http.MethodConnect
	case "OPTIONS":
		return http.MethodOptions
	case "TRACE":
		return http.MethodTrace
	}
	fatal(fmt.Sprintf("Invalid HTTP Method %v", method))
	return ""
}

func htCreate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	fnName := c.String("function")
	if len(fnName) == 0 {
		fatal("Need a function name to create a trigger, use --function")
	}
	triggerUrl := c.String("url")
	if len(triggerUrl) == 0 {
		fatal("Need a trigger URL, use --url")
	}
	method := c.String("method")
	if len(method) == 0 {
		method = "GET"
	}

	// just name triggers by uuid.
	triggerName := uuid.NewV4().String()

	ht := &crd.HTTPTrigger{
		Metadata: metav1.ObjectMeta{
			Name:      triggerName,
			Namespace: metav1.NamespaceDefault,
		},
		Spec: fission.HTTPTriggerSpec{
			RelativeURL: triggerUrl,
			Method:      getMethod(method),
			FunctionReference: fission.FunctionReference{
				Type: fission.FunctionReferenceTypeFunctionName,
				Name: fnName,
			},
		},
	}

	_, err := client.HTTPTriggerCreate(ht)
	checkErr(err, "create HTTP trigger")

	fmt.Printf("trigger '%v' created\n", triggerName)
	return err
}

func htGet(c *cli.Context) error {
	return nil
}

func htUpdate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))
	htName := c.String("name")
	if len(htName) == 0 {
		fatal("Need name of trigger, use --name")
	}

	// update function ref
	newFn := c.String("function")
	if len(newFn) == 0 {
		fatal("Nothing to update. Use --function to specify a new function.")
	}

	ht, err := client.HTTPTriggerGet(&metav1.ObjectMeta{
		Name:      htName,
		Namespace: metav1.NamespaceDefault,
	})
	checkErr(err, "get HTTP trigger")

	if len(newFn) > 0 {
		ht.Spec.FunctionReference.Name = newFn
	}

	_, err = client.HTTPTriggerUpdate(ht)
	checkErr(err, "update HTTP trigger")

	fmt.Printf("trigger '%v' updated\n", htName)
	return nil
}

func htDelete(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))
	htName := c.String("name")
	if len(htName) == 0 {
		fatal("Need name of trigger to delete, use --name")
	}

	err := client.HTTPTriggerDelete(&metav1.ObjectMeta{
		Name:      htName,
		Namespace: metav1.NamespaceDefault,
	})
	checkErr(err, "delete trigger")

	fmt.Printf("trigger '%v' deleted\n", htName)
	return nil
}

func htList(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	hts, err := client.HTTPTriggerList()
	checkErr(err, "list HTTP triggers")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)

	fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", "NAME", "METHOD", "HOST", "URL", "FUNCTION_NAME")
	for _, ht := range hts {
		fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n",
			ht.Metadata.Name, ht.Spec.Method, ht.Spec.Host, ht.Spec.RelativeURL, ht.Spec.FunctionReference.Name)
	}
	w.Flush()

	return nil
}
<commit_msg>Show warning when trying to create a route with non-existent function (#539)<commit_after>/*
Copyright 2016 The Fission Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"net/http"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/satori/go.uuid"
	"github.com/urfave/cli"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"github.com/fission/fission"
	"github.com/fission/fission/controller/client"
	"github.com/fission/fission/crd"
)

// returns one of http.Method*
func getMethod(method string) string {
	switch strings.ToUpper(method) {
	case "GET":
		return http.MethodGet
	case "HEAD":
		return http.MethodHead
	case "POST":
		return http.MethodPost
	case "PUT":
		return http.MethodPut
	case "PATCH":
		return http.MethodPatch
	case "DELETE":
		return http.MethodDelete
	case "CONNECT":
		return http.MethodConnect
	case "OPTIONS":
		return http.MethodOptions
	case "TRACE":
		return http.MethodTrace
	}
	fatal(fmt.Sprintf("Invalid HTTP Method %v", method))
	return ""
}

func checkFunctionExistence(fissionClient *client.Client, fnName string) {
	meta := &metav1.ObjectMeta{
		Name:      fnName,
		Namespace: metav1.NamespaceDefault,
	}
	_, err := fissionClient.FunctionGet(meta)
	if err != nil {
		fmt.Printf("function '%v' does not exist, use 'fission function create --name %v ...' to create the function\n", fnName, fnName)
	}
}

func htCreate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	fnName := c.String("function")
	if len(fnName) == 0 {
		fatal("Need a function name to create a trigger, use --function")
	}
	triggerUrl := c.String("url")
	if len(triggerUrl) == 0 {
		fatal("Need a trigger URL, use --url")
	}
	method := c.String("method")
	if len(method) == 0 {
		method = "GET"
	}

	checkFunctionExistence(client, fnName)

	// just name triggers by uuid.
	triggerName := uuid.NewV4().String()

	ht := &crd.HTTPTrigger{
		Metadata: metav1.ObjectMeta{
			Name:      triggerName,
			Namespace: metav1.NamespaceDefault,
		},
		Spec: fission.HTTPTriggerSpec{
			RelativeURL: triggerUrl,
			Method:      getMethod(method),
			FunctionReference: fission.FunctionReference{
				Type: fission.FunctionReferenceTypeFunctionName,
				Name: fnName,
			},
		},
	}

	_, err := client.HTTPTriggerCreate(ht)
	checkErr(err, "create HTTP trigger")

	fmt.Printf("trigger '%v' created\n", triggerName)
	return err
}

func htGet(c *cli.Context) error {
	return nil
}

func htUpdate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))
	htName := c.String("name")
	if len(htName) == 0 {
		fatal("Need name of trigger, use --name")
	}

	// update function ref
	newFn := c.String("function")
	if len(newFn) == 0 {
		fatal("Nothing to update. Use --function to specify a new function.")
	}

	checkFunctionExistence(client, newFn)

	ht, err := client.HTTPTriggerGet(&metav1.ObjectMeta{
		Name:      htName,
		Namespace: metav1.NamespaceDefault,
	})
	checkErr(err, "get HTTP trigger")

	if len(newFn) > 0 {
		ht.Spec.FunctionReference.Name = newFn
	}

	_, err = client.HTTPTriggerUpdate(ht)
	checkErr(err, "update HTTP trigger")

	fmt.Printf("trigger '%v' updated\n", htName)
	return nil
}

func htDelete(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))
	htName := c.String("name")
	if len(htName) == 0 {
		fatal("Need name of trigger to delete, use --name")
	}

	err := client.HTTPTriggerDelete(&metav1.ObjectMeta{
		Name:      htName,
		Namespace: metav1.NamespaceDefault,
	})
	checkErr(err, "delete trigger")

	fmt.Printf("trigger '%v' deleted\n", htName)
	return nil
}

func htList(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	hts, err := client.HTTPTriggerList()
	checkErr(err, "list HTTP triggers")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)

	fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", "NAME", "METHOD", "HOST", "URL", "FUNCTION_NAME")
	for _, ht := range hts {
		fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n",
			ht.Metadata.Name, ht.Spec.Method, ht.Spec.Host, ht.Spec.RelativeURL, ht.Spec.FunctionReference.Name)
	}
	w.Flush()

	return nil
}
<|endoftext|>