<commit_before>package glock

import (
	"sort"
	"sync"
	"time"
)

type mockTriggers []*mockTrigger

func (mt mockTriggers) Len() int {
	return len(mt)
}
func (mt mockTriggers) Less(i, j int) bool {
	return mt[i].trigger.Before(mt[j].trigger)
}
func (mt mockTriggers) Swap(i, j int) {
	mt[i], mt[j] = mt[j], mt[i]
}

type mockTrigger struct {
	trigger time.Time
	ch      chan time.Time
}

// MockClock is an implementation of Clock that can be moved forward in time
// in increments for testing code that relies on timeouts or other time-sensitive
// constructs.
type MockClock struct {
	fakeTime time.Time

	afterLock sync.Mutex
	triggers  mockTriggers
	afterArgs []time.Duration

	tickerLock sync.Mutex
	tickers    []*mockTicker
	tickerArgs []time.Duration
}

// NewMockClock creates a new instance of MockClock with the internal time set
// to time.Now()
func NewMockClock() *MockClock {
	return &MockClock{
		fakeTime: time.Now(),

		tickers: make([]*mockTicker, 0),

		afterArgs:  make([]time.Duration, 0),
		tickerArgs: make([]time.Duration, 0),
	}
}

func (mc *MockClock) processTickers() {
	mc.tickerLock.Lock()
	defer mc.tickerLock.Unlock()

	now := mc.Now()
	for _, ticker := range mc.tickers {
		ticker.process(now)
	}
}

func (mc *MockClock) processTriggers() {
	mc.afterLock.Lock()
	mc.afterLock.Unlock()

	now := mc.Now()
	triggered := 0
	for _, trigger := range mc.triggers {
		if trigger.trigger.Before(now) || trigger.trigger.Equal(now) {
			trigger.ch <- trigger.trigger
			triggered++
		}
	}

	mc.triggers = mc.triggers[triggered:]
}

// SetCurrent sets the internal MockClock time to the supplied time.
func (mc *MockClock) SetCurrent(current time.Time) {
	mc.fakeTime = current
}

// Advance will advance the internal MockClock time by the supplied time.
func (mc *MockClock) Advance(duration time.Duration) {
	mc.fakeTime = mc.fakeTime.Add(duration)
	mc.processTickers()
	mc.processTriggers()
}

// Now returns the current time internal to the MockClock
func (mc *MockClock) Now() time.Time {
	return mc.fakeTime
}

// After returns a channel that will be sent the current internal MockClock
// time once the MockClock's internal time is at or past the provided duration
func (mc *MockClock) After(duration time.Duration) <-chan time.Time {
	mc.afterLock.Lock()
	defer mc.afterLock.Unlock()

	trigger := &mockTrigger{
		trigger: mc.fakeTime.Add(duration),
		ch:      make(chan time.Time, 1),
	}
	mc.triggers = append(mc.triggers, trigger)
	sort.Sort(mc.triggers)

	mc.afterArgs = append(mc.afterArgs, duration)

	return trigger.ch
}

// Sleep will block until the internal MockClock time is at or past the
// provided duration
func (mc *MockClock) Sleep(duration time.Duration) {
	<-mc.After(duration)
}

// GetAfterArgs returns the duration of each call to After in the
// same order as they were called. The list is cleared each time
// GetAfterArgs is called.
func (mc *MockClock) GetAfterArgs() []time.Duration {
	mc.afterLock.Lock()
	defer mc.afterLock.Unlock()

	args := mc.afterArgs
	mc.afterArgs = mc.afterArgs[:0]
	return args
}

// GetTickerArgs returns the duration of each call to create a new
// ticker in the same order as they were called. The list is cleared
// each time GetTickerArgs is called.
func (mc *MockClock) GetTickerArgs() []time.Duration {
	mc.tickerLock.Lock()
	defer mc.tickerLock.Unlock()

	args := mc.tickerArgs
	mc.tickerArgs = mc.tickerArgs[:0]
	return args
}

type mockTicker struct {
	clock    *MockClock
	duration time.Duration

	started  time.Time
	nextTick time.Time

	processLock  sync.Mutex
	processQueue []time.Time

	writeLock sync.Mutex
	writing   bool
	ch        chan time.Time

	stopped bool
}

// NewTicker creates a new Ticker tied to the internal MockClock time that ticks
// at intervals similar to time.NewTicker().  It will also skip or drop ticks
// for slow readers similar to time.NewTicker() as well.
func (mc *MockClock) NewTicker(duration time.Duration) Ticker {
	if duration == 0 {
		panic("duration cannot be 0")
	}

	now := mc.Now()

	ft := &mockTicker{
		clock:    mc,
		duration: duration,

		started:  now,
		nextTick: now.Add(duration),

		processQueue: make([]time.Time, 0),
		ch:           make(chan time.Time),
	}

	mc.tickerLock.Lock()
	mc.tickers = append(mc.tickers, ft)
	mc.tickerArgs = append(mc.tickerArgs, duration)
	mc.tickerLock.Unlock()

	return ft
}

func (mt *mockTicker) process(now time.Time) {
	if mt.stopped {
		return
	}

	mt.processLock.Lock()
	mt.processQueue = append(mt.processQueue, now)
	mt.processLock.Unlock()

	if !mt.writing && (mt.nextTick.Before(now) || mt.nextTick.Equal(now)) {
		mt.writeLock.Lock()

		mt.writing = true
		go func() {
			defer mt.writeLock.Unlock()

			for {
				mt.processLock.Lock()
				if len(mt.processQueue) == 0 {
					mt.processLock.Unlock()
					break
				}

				procTime := mt.processQueue[0]
				mt.processQueue = mt.processQueue[1:]

				mt.processLock.Unlock()

				if mt.nextTick.After(procTime) {
					continue
				}

				mt.ch <- mt.nextTick

				durationMod := procTime.Sub(mt.started) % mt.duration

				if durationMod == 0 {
					mt.nextTick = procTime.Add(mt.duration)
				} else if procTime.Sub(mt.nextTick) > mt.duration {
					mt.nextTick = procTime.Add(mt.duration - durationMod)
				} else {
					mt.nextTick = mt.nextTick.Add(mt.duration)
				}
			}

			mt.writing = false
		}()
	}
}

// Chan returns a channel which will receive the MockClock's internal time
// at the interval given when creating the ticker.
func (mt *mockTicker) Chan() <-chan time.Time {
	return mt.ch
}

// Stop will stop the ticker from ticking
func (mt *mockTicker) Stop() {
	mt.stopped = true
}
<commit_msg>Add a function to set the time for a new mock clock<commit_after>package glock

import (
	"sort"
	"sync"
	"time"
)

type mockTriggers []*mockTrigger

func (mt mockTriggers) Len() int {
	return len(mt)
}
func (mt mockTriggers) Less(i, j int) bool {
	return mt[i].trigger.Before(mt[j].trigger)
}
func (mt mockTriggers) Swap(i, j int) {
	mt[i], mt[j] = mt[j], mt[i]
}

type mockTrigger struct {
	trigger time.Time
	ch      chan time.Time
}

// MockClock is an implementation of Clock that can be moved forward in time
// in increments for testing code that relies on timeouts or other time-sensitive
// constructs.
type MockClock struct {
	fakeTime time.Time

	afterLock sync.Mutex
	triggers  mockTriggers
	afterArgs []time.Duration

	tickerLock sync.Mutex
	tickers    []*mockTicker
	tickerArgs []time.Duration
}

// NewMockClock creates a new MockClock with the internal time set
// to time.Now()
func NewMockClock() *MockClock {
	return NewMockClockAt(time.Now())
}

// NewMockClockAt creates a new MockClick with the internal time set
// to the provided time.
func NewMockClockAt(now time.Time) *MockClock {
	return &MockClock{
		fakeTime: now,

		tickers: make([]*mockTicker, 0),

		afterArgs:  make([]time.Duration, 0),
		tickerArgs: make([]time.Duration, 0),
	}
}

func (mc *MockClock) processTickers() {
	mc.tickerLock.Lock()
	defer mc.tickerLock.Unlock()

	now := mc.Now()
	for _, ticker := range mc.tickers {
		ticker.process(now)
	}
}

func (mc *MockClock) processTriggers() {
	mc.afterLock.Lock()
	mc.afterLock.Unlock()

	now := mc.Now()
	triggered := 0
	for _, trigger := range mc.triggers {
		if trigger.trigger.Before(now) || trigger.trigger.Equal(now) {
			trigger.ch <- trigger.trigger
			triggered++
		}
	}

	mc.triggers = mc.triggers[triggered:]
}

// SetCurrent sets the internal MockClock time to the supplied time.
func (mc *MockClock) SetCurrent(current time.Time) {
	mc.fakeTime = current
}

// Advance will advance the internal MockClock time by the supplied time.
func (mc *MockClock) Advance(duration time.Duration) {
	mc.fakeTime = mc.fakeTime.Add(duration)
	mc.processTickers()
	mc.processTriggers()
}

// Now returns the current time internal to the MockClock
func (mc *MockClock) Now() time.Time {
	return mc.fakeTime
}

// After returns a channel that will be sent the current internal MockClock
// time once the MockClock's internal time is at or past the provided duration
func (mc *MockClock) After(duration time.Duration) <-chan time.Time {
	mc.afterLock.Lock()
	defer mc.afterLock.Unlock()

	trigger := &mockTrigger{
		trigger: mc.fakeTime.Add(duration),
		ch:      make(chan time.Time, 1),
	}
	mc.triggers = append(mc.triggers, trigger)
	sort.Sort(mc.triggers)

	mc.afterArgs = append(mc.afterArgs, duration)

	return trigger.ch
}

// Sleep will block until the internal MockClock time is at or past the
// provided duration
func (mc *MockClock) Sleep(duration time.Duration) {
	<-mc.After(duration)
}

// GetAfterArgs returns the duration of each call to After in the
// same order as they were called. The list is cleared each time
// GetAfterArgs is called.
func (mc *MockClock) GetAfterArgs() []time.Duration {
	mc.afterLock.Lock()
	defer mc.afterLock.Unlock()

	args := mc.afterArgs
	mc.afterArgs = mc.afterArgs[:0]
	return args
}

// GetTickerArgs returns the duration of each call to create a new
// ticker in the same order as they were called. The list is cleared
// each time GetTickerArgs is called.
func (mc *MockClock) GetTickerArgs() []time.Duration {
	mc.tickerLock.Lock()
	defer mc.tickerLock.Unlock()

	args := mc.tickerArgs
	mc.tickerArgs = mc.tickerArgs[:0]
	return args
}

type mockTicker struct {
	clock    *MockClock
	duration time.Duration

	started  time.Time
	nextTick time.Time

	processLock  sync.Mutex
	processQueue []time.Time

	writeLock sync.Mutex
	writing   bool
	ch        chan time.Time

	stopped bool
}

// NewTicker creates a new Ticker tied to the internal MockClock time that ticks
// at intervals similar to time.NewTicker().  It will also skip or drop ticks
// for slow readers similar to time.NewTicker() as well.
func (mc *MockClock) NewTicker(duration time.Duration) Ticker {
	if duration == 0 {
		panic("duration cannot be 0")
	}

	now := mc.Now()

	ft := &mockTicker{
		clock:    mc,
		duration: duration,

		started:  now,
		nextTick: now.Add(duration),

		processQueue: make([]time.Time, 0),
		ch:           make(chan time.Time),
	}

	mc.tickerLock.Lock()
	mc.tickers = append(mc.tickers, ft)
	mc.tickerArgs = append(mc.tickerArgs, duration)
	mc.tickerLock.Unlock()

	return ft
}

func (mt *mockTicker) process(now time.Time) {
	if mt.stopped {
		return
	}

	mt.processLock.Lock()
	mt.processQueue = append(mt.processQueue, now)
	mt.processLock.Unlock()

	if !mt.writing && (mt.nextTick.Before(now) || mt.nextTick.Equal(now)) {
		mt.writeLock.Lock()

		mt.writing = true
		go func() {
			defer mt.writeLock.Unlock()

			for {
				mt.processLock.Lock()
				if len(mt.processQueue) == 0 {
					mt.processLock.Unlock()
					break
				}

				procTime := mt.processQueue[0]
				mt.processQueue = mt.processQueue[1:]

				mt.processLock.Unlock()

				if mt.nextTick.After(procTime) {
					continue
				}

				mt.ch <- mt.nextTick

				durationMod := procTime.Sub(mt.started) % mt.duration

				if durationMod == 0 {
					mt.nextTick = procTime.Add(mt.duration)
				} else if procTime.Sub(mt.nextTick) > mt.duration {
					mt.nextTick = procTime.Add(mt.duration - durationMod)
				} else {
					mt.nextTick = mt.nextTick.Add(mt.duration)
				}
			}

			mt.writing = false
		}()
	}
}

// Chan returns a channel which will receive the MockClock's internal time
// at the interval given when creating the ticker.
func (mt *mockTicker) Chan() <-chan time.Time {
	return mt.ch
}

// Stop will stop the ticker from ticking
func (mt *mockTicker) Stop() {
	mt.stopped = true
}
<|endoftext|>


<commit_before>package litebrite

import (
	"bytes"
	"go/scanner"
	"go/token"
	"html/template"
)

type codeSegment struct {
	Code  string // a segment of source code with the same style
	Pos   int    // the position of the segment in the source
	Tok   token.Token // the token type of the segment
	Class string
}

// getSegments splits the source into same-token-type chunks.
func getSegments(src []byte) []*codeSegment {
	segments := make([]*codeSegment, 0)

	// find the starting positions of all segments
	var s scanner.Scanner
	fset := token.NewFileSet()
	file := fset.AddFile("", fset.Base(), len(src))
	s.Init(file, src, nil, 1)
	for {
		pos, tok, _ := s.Scan()
		if tok == token.EOF {
			break
		}
		segment := &codeSegment{Pos: int(pos)-1, Tok: tok} // WTF -1
		segments = append(segments, segment)
	}

	// split the source at each position to get segments
	for i, segment := range segments {
		if i+1 == len(segments) {
			segment.Code = string(src[segment.Pos:])
		} else {
			next := segments[i+1]
			segment.Code = string(src[segment.Pos:next.Pos])
		}
	}

	return segments
}

const ELEM = `{{with .Class}}<div class="{{.}}">{{end}}{{.Code}}{{with .Class}}</div>{{end}}`

var elemT = template.Must(template.New("golang-elem").Parse(ELEM))

// buildHTML constructs an HTML string of elements from the segments in src.
func buildHTML(src []*codeSegment) string {
	var b bytes.Buffer
	for _, segment := range src {
		elemT.Execute(&b, segment)
	}

	return string(b.Bytes())
}

// Highlighter contains the CSS class names that are applied to the
// corresponding source code token types.
type Highlighter struct {
	OperatorClass string
	IdentClass string
	LiteralClass string
	KeywordClass string
	CommentClass string
}

// highlightSegment adds the CSS class name specified by h to the segment.
func (h *Highlighter) highlightSegment(s *codeSegment) {
	switch {
	case s.Tok.IsKeyword():
		s.Class = h.KeywordClass
	case s.Tok.IsLiteral():
		if s.Tok == token.IDENT {
			s.Class = h.IdentClass
		} else {
			s.Class = h.LiteralClass
		}
	case s.Tok.IsOperator():
		if s.Tok == token.SEMICOLON && s.Code != ";" {
			return
		}
		s.Class = h.OperatorClass
	case s.Tok == token.COMMENT:
		s.Class = h.CommentClass
	default:
		panic("unknown token type!")
	}
}

// Highlight returns an HTML fragment containing elements for all Go tokens
// in src.  The elements will be of the form
CODE

// where TYPE_CLASS is the CSS class name provided in h corresponding to the
// token type of CODE.  For instance, if CODE is a keyword, then TYPE_CLASS
// will be h.keywordClass.
func (h *Highlighter) Highlight(src string) string {
	data := []byte(src)
	segments := getSegments(data)
	for _, segment := range segments {
		h.highlightSegment(segment)
	}
	return buildHTML(segments)
}
<commit_msg>using byte slices instead of strings<commit_after>package litebrite

import (
	"bytes"
	"go/scanner"
	"go/token"
	"html/template"
)

type codeSegment struct {
	Code  string      // a segment of source code with the same style
	Pos   int         // the position of the segment in the source
	Tok   token.Token // the token type of the segment
	Class string
}

// getSegments splits the source into same-token-type chunks.
func getSegments(src []byte) []*codeSegment {
	segments := make([]*codeSegment, 0)

	// find the starting positions of all segments
	var s scanner.Scanner
	fset := token.NewFileSet()
	file := fset.AddFile("", fset.Base(), len(src))
	s.Init(file, src, nil, 1)
	for {
		filePos, tok, _ := s.Scan()
		if tok == token.EOF {
			break
		}

		pos := int(filePos) - file.Base() // pos in this source only
		segment := &codeSegment{Pos: pos, Tok: tok}
		segments = append(segments, segment)
	}

	// split the source at each position to get segments
	for i, segment := range segments {
		if i+1 == len(segments) {
			segment.Code = string(src[segment.Pos:])
		} else {
			next := segments[i+1]
			segment.Code = string(src[segment.Pos:next.Pos])
		}
	}

	return segments
}

const ELEM = `{{with .Class}}<div class="{{.}}">{{end}}{{.Code}}{{with .Class}}</div>{{end}}`

var elemT = template.Must(template.New("golang-elem").Parse(ELEM))

// buildHTML constructs an HTML string of elements from the segments in src.
func buildHTML(src []*codeSegment) []byte {
	var b bytes.Buffer
	for _, segment := range src {
		elemT.Execute(&b, segment)
	}

	return b.Bytes()
}

// Highlighter contains the CSS class names that are applied to the
// corresponding source code token types and the desired width of tabs.
type Highlighter struct {
	OperatorClass string
	IdentClass    string
	LiteralClass  string
	KeywordClass  string
	CommentClass  string
}

// highlightSegment adds the CSS class name specified by h to the segment.
func (h *Highlighter) highlightSegment(s *codeSegment) {
	switch {
	case s.Tok.IsKeyword():
		s.Class = h.KeywordClass
	case s.Tok.IsLiteral():
		if s.Tok == token.IDENT {
			s.Class = h.IdentClass
		} else {
			s.Class = h.LiteralClass
		}
	case s.Tok.IsOperator():
		if s.Tok == token.SEMICOLON && len(s.Code) > 0 && s.Code[0] != ';' {
			return
		}
		s.Class = h.OperatorClass
	case s.Tok == token.COMMENT:
		s.Class = h.CommentClass
	default:
		panic("unknown token type!")
	}
}

// Highlight returns an HTML fragment containing elements for all Go tokens in
// src.  The elements will be of the form `<div class="TYPE_CLASS">CODE</div>`
// where `TYPE_CLASS` is the CSS class name provided in `h` corresponding to
// the token type of `CODE`.  For instance, if `CODE` is a keyword, then
// `TYPE_CLASS` will be `h.keywordClass`.
func (h *Highlighter) Highlight(src []byte) []byte {
	segments := getSegments(src)
	for _, segment := range segments {
		h.highlightSegment(segment)
	}
	return buildHTML(segments)
}
<|endoftext|>


<commit_before>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"fmt"

	"github.com/keybase/client/go/protocol/keybase1"
)

// NewInitModeFromType returns an InitMode object corresponding to the
// given type.
func NewInitModeFromType(t InitModeType) InitMode {
	switch t {
	case InitDefault:
		return modeDefault{}
	case InitMinimal:
		return modeMinimal{}
	case InitSingleOp:
		return modeSingleOp{modeDefault{}}
	case InitConstrained:
		return modeConstrained{modeDefault{}}
	default:
		panic(fmt.Sprintf("Unknown mode: %s", t))
	}
}

// Default mode:

type modeDefault struct {
}

func (md modeDefault) Type() InitModeType {
	return InitDefault
}

func (md modeDefault) BlockWorkers() int {
	return defaultBlockRetrievalWorkerQueueSize
}

func (md modeDefault) PrefetchWorkers() int {
	return defaultPrefetchWorkerQueueSize
}

func (md modeDefault) RekeyWorkers() int {
	return 16
}

func (md modeDefault) IsTestMode() bool {
	return false
}

func (md modeDefault) DirtyBlockCacheEnabled() bool {
	return true
}

func (md modeDefault) BackgroundFlushesEnabled() bool {
	return true
}

func (md modeDefault) MetricsEnabled() bool {
	return true
}

func (md modeDefault) ConflictResolutionEnabled() bool {
	return true
}

func (md modeDefault) BlockManagementEnabled() bool {
	return true
}

func (md modeDefault) QuotaReclamationEnabled() bool {
	return true
}

func (md modeDefault) NodeCacheEnabled() bool {
	return true
}

func (md modeDefault) TLFUpdatesEnabled() bool {
	return true
}

func (md modeDefault) KBFSServiceEnabled() bool {
	return true
}

func (md modeDefault) JournalEnabled() bool {
	return true
}

func (md modeDefault) UnmergedTLFsEnabled() bool {
	return true
}

func (md modeDefault) ServiceKeepaliveEnabled() bool {
	return true
}

func (md modeDefault) TLFEditHistoryEnabled() bool {
	return true
}

func (md modeDefault) ClientType() keybase1.ClientType {
	return keybase1.ClientType_KBFS
}

func (md modeDefault) LocalHTTPServerEnabled() bool {
	return true
}

// Minimal mode:

type modeMinimal struct {
}

func (mm modeMinimal) Type() InitModeType {
	return InitMinimal
}

func (mm modeMinimal) BlockWorkers() int {
	// In minimal mode, block re-embedding is not required, so we
	// don't fetch the unembedded blocks..
	return 0
}

func (mm modeMinimal) PrefetchWorkers() int {
	return 0
}

func (mm modeMinimal) RekeyWorkers() int {
	return 4
}

func (mm modeMinimal) IsTestMode() bool {
	return false
}

func (mm modeMinimal) DirtyBlockCacheEnabled() bool {
	// No blocks will be dirtied in minimal mode, so don't bother with
	// the dirty block cache.
	return false
}

func (mm modeMinimal) BackgroundFlushesEnabled() bool {
	// Don't do background flushes when in minimal mode, since there
	// shouldn't be any data writes.
	return false
}

func (mm modeMinimal) MetricsEnabled() bool {
	return false
}

func (mm modeMinimal) ConflictResolutionEnabled() bool {
	// No need to run CR if there won't be any data writes on this
	// device.  (There may still be rekey writes, but we don't allow
	// conflicts to happen in that case.)
	return false
}

func (mm modeMinimal) BlockManagementEnabled() bool {
	// If this device is in minimal mode and won't be doing any data
	// writes, no need deal with block-level cleanup operations.
	// TODO: in the future it might still be useful to have
	// e.g. mobile devices doing QR.
	return false
}

func (mm modeMinimal) QuotaReclamationEnabled() bool {
	return false
}

func (mm modeMinimal) NodeCacheEnabled() bool {
	// If we're in minimal mode, let the node cache remain nil to
	// ensure that the user doesn't try any data reads or writes.
	return false
}

func (mm modeMinimal) TLFUpdatesEnabled() bool {
	return true
}

func (mm modeMinimal) KBFSServiceEnabled() bool {
	return false
}

func (mm modeMinimal) JournalEnabled() bool {
	return false
}

func (mm modeMinimal) UnmergedTLFsEnabled() bool {
	// Writes aren't allowed, so unmerged TLFs on this device
	// shouldn't be possible.
	return false
}

func (mm modeMinimal) ServiceKeepaliveEnabled() bool {
	return false
}

func (mm modeMinimal) TLFEditHistoryEnabled() bool {
	return false
}

func (mm modeMinimal) ClientType() keybase1.ClientType {
	return keybase1.ClientType_KBFS
}

func (mm modeMinimal) LocalHTTPServerEnabled() bool {
	return false
}

// Single op mode:

type modeSingleOp struct {
	InitMode
}

func (mso modeSingleOp) Type() InitModeType {
	return InitSingleOp
}

func (mso modeSingleOp) RekeyWorkers() int {
	// Just block all rekeys and don't bother cleaning up requests
	// since the process is short lived anyway.
	return 0
}

func (mso modeSingleOp) QuotaReclamationEnabled() bool {
	return false
}

func (mso modeSingleOp) TLFUpdatesEnabled() bool {
	return false
}

func (mso modeSingleOp) KBFSServiceEnabled() bool {
	return false
}

func (mso modeSingleOp) UnmergedTLFsEnabled() bool {
	// There's basically no way for a TLF to start off as unmerged
	// since single-ops should be using a fresh journal.
	return false
}

func (mso modeSingleOp) TLFEditHistoryEnabled() bool {
	return false
}

func (mso modeSingleOp) ClientType() keybase1.ClientType {
	return keybase1.ClientType_NONE
}

func (mso modeSingleOp) LocalHTTPServerEnabled() bool {
	return false
}

// Constrained mode:

type modeConstrained struct {
	InitMode
}

func (mc modeConstrained) Type() InitModeType {
	return InitConstrained
}

func (mc modeConstrained) BlockWorkers() int {
	return 1
}

func (mc modeConstrained) PrefetchWorkers() int {
	return 0
}

func (mc modeConstrained) RekeyWorkers() int {
	return 4
}

func (mc modeConstrained) BackgroundFlushesEnabled() bool {
	// TODO: turn this on once we allow mobile writes.
	return false
}

func (mc modeConstrained) ConflictResolutionEnabled() bool {
	// TODO: turn this on once we allow mobile writes.
	return false
}

func (mc modeConstrained) QuotaReclamationEnabled() bool {
	// TODO: turn this on once we allow mobile writes.
	return false
}

func (mc modeConstrained) KBFSServiceEnabled() bool {
	return false
}

func (mc modeConstrained) JournalEnabled() bool {
	// TODO: turn this on once we allow mobile writes.
	return false
}

func (mc modeConstrained) UnmergedTLFsEnabled() bool {
	// TODO: turn this on once we allow mobile writes.
	return false
}

func (mc modeConstrained) ServiceKeepaliveEnabled() bool {
	return false
}

func (mc modeConstrained) TLFEditHistoryEnabled() bool {
	return false
}

func (mc modeConstrained) LocalHTTPServerEnabled() bool {
	return true
}

// Wrapper for tests.

type modeTest struct {
	InitMode
}

func (mt modeTest) IsTestMode() bool {
	return true
}
<commit_msg>turn on a bunch of things for mobile<commit_after>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"fmt"

	"github.com/keybase/client/go/protocol/keybase1"
)

// NewInitModeFromType returns an InitMode object corresponding to the
// given type.
func NewInitModeFromType(t InitModeType) InitMode {
	switch t {
	case InitDefault:
		return modeDefault{}
	case InitMinimal:
		return modeMinimal{}
	case InitSingleOp:
		return modeSingleOp{modeDefault{}}
	case InitConstrained:
		return modeConstrained{modeDefault{}}
	default:
		panic(fmt.Sprintf("Unknown mode: %s", t))
	}
}

// Default mode:

type modeDefault struct {
}

func (md modeDefault) Type() InitModeType {
	return InitDefault
}

func (md modeDefault) BlockWorkers() int {
	return defaultBlockRetrievalWorkerQueueSize
}

func (md modeDefault) PrefetchWorkers() int {
	return defaultPrefetchWorkerQueueSize
}

func (md modeDefault) RekeyWorkers() int {
	return 16
}

func (md modeDefault) IsTestMode() bool {
	return false
}

func (md modeDefault) DirtyBlockCacheEnabled() bool {
	return true
}

func (md modeDefault) BackgroundFlushesEnabled() bool {
	return true
}

func (md modeDefault) MetricsEnabled() bool {
	return true
}

func (md modeDefault) ConflictResolutionEnabled() bool {
	return true
}

func (md modeDefault) BlockManagementEnabled() bool {
	return true
}

func (md modeDefault) QuotaReclamationEnabled() bool {
	return true
}

func (md modeDefault) NodeCacheEnabled() bool {
	return true
}

func (md modeDefault) TLFUpdatesEnabled() bool {
	return true
}

func (md modeDefault) KBFSServiceEnabled() bool {
	return true
}

func (md modeDefault) JournalEnabled() bool {
	return true
}

func (md modeDefault) UnmergedTLFsEnabled() bool {
	return true
}

func (md modeDefault) ServiceKeepaliveEnabled() bool {
	return true
}

func (md modeDefault) TLFEditHistoryEnabled() bool {
	return true
}

func (md modeDefault) ClientType() keybase1.ClientType {
	return keybase1.ClientType_KBFS
}

func (md modeDefault) LocalHTTPServerEnabled() bool {
	return true
}

// Minimal mode:

type modeMinimal struct {
}

func (mm modeMinimal) Type() InitModeType {
	return InitMinimal
}

func (mm modeMinimal) BlockWorkers() int {
	// In minimal mode, block re-embedding is not required, so we
	// don't fetch the unembedded blocks..
	return 0
}

func (mm modeMinimal) PrefetchWorkers() int {
	return 0
}

func (mm modeMinimal) RekeyWorkers() int {
	return 4
}

func (mm modeMinimal) IsTestMode() bool {
	return false
}

func (mm modeMinimal) DirtyBlockCacheEnabled() bool {
	// No blocks will be dirtied in minimal mode, so don't bother with
	// the dirty block cache.
	return false
}

func (mm modeMinimal) BackgroundFlushesEnabled() bool {
	// Don't do background flushes when in minimal mode, since there
	// shouldn't be any data writes.
	return false
}

func (mm modeMinimal) MetricsEnabled() bool {
	return false
}

func (mm modeMinimal) ConflictResolutionEnabled() bool {
	// No need to run CR if there won't be any data writes on this
	// device.  (There may still be rekey writes, but we don't allow
	// conflicts to happen in that case.)
	return false
}

func (mm modeMinimal) BlockManagementEnabled() bool {
	// If this device is in minimal mode and won't be doing any data
	// writes, no need deal with block-level cleanup operations.
	// TODO: in the future it might still be useful to have
	// e.g. mobile devices doing QR.
	return false
}

func (mm modeMinimal) QuotaReclamationEnabled() bool {
	return false
}

func (mm modeMinimal) NodeCacheEnabled() bool {
	// If we're in minimal mode, let the node cache remain nil to
	// ensure that the user doesn't try any data reads or writes.
	return false
}

func (mm modeMinimal) TLFUpdatesEnabled() bool {
	return true
}

func (mm modeMinimal) KBFSServiceEnabled() bool {
	return false
}

func (mm modeMinimal) JournalEnabled() bool {
	return false
}

func (mm modeMinimal) UnmergedTLFsEnabled() bool {
	// Writes aren't allowed, so unmerged TLFs on this device
	// shouldn't be possible.
	return false
}

func (mm modeMinimal) ServiceKeepaliveEnabled() bool {
	return false
}

func (mm modeMinimal) TLFEditHistoryEnabled() bool {
	return false
}

func (mm modeMinimal) ClientType() keybase1.ClientType {
	return keybase1.ClientType_KBFS
}

func (mm modeMinimal) LocalHTTPServerEnabled() bool {
	return false
}

// Single op mode:

type modeSingleOp struct {
	InitMode
}

func (mso modeSingleOp) Type() InitModeType {
	return InitSingleOp
}

func (mso modeSingleOp) RekeyWorkers() int {
	// Just block all rekeys and don't bother cleaning up requests
	// since the process is short lived anyway.
	return 0
}

func (mso modeSingleOp) QuotaReclamationEnabled() bool {
	return false
}

func (mso modeSingleOp) TLFUpdatesEnabled() bool {
	return false
}

func (mso modeSingleOp) KBFSServiceEnabled() bool {
	return false
}

func (mso modeSingleOp) UnmergedTLFsEnabled() bool {
	// There's basically no way for a TLF to start off as unmerged
	// since single-ops should be using a fresh journal.
	return false
}

func (mso modeSingleOp) TLFEditHistoryEnabled() bool {
	return false
}

func (mso modeSingleOp) ClientType() keybase1.ClientType {
	return keybase1.ClientType_NONE
}

func (mso modeSingleOp) LocalHTTPServerEnabled() bool {
	return false
}

// Constrained mode:

type modeConstrained struct {
	InitMode
}

func (mc modeConstrained) Type() InitModeType {
	return InitConstrained
}

func (mc modeConstrained) BlockWorkers() int {
	return 1
}

func (mc modeConstrained) PrefetchWorkers() int {
	return 0
}

func (mc modeConstrained) RekeyWorkers() int {
	return 4
}

func (mc modeConstrained) BackgroundFlushesEnabled() bool {
	return true
}

func (mc modeConstrained) ConflictResolutionEnabled() bool {
	return true
}

func (mc modeConstrained) QuotaReclamationEnabled() bool {
	return true
}

func (mc modeConstrained) KBFSServiceEnabled() bool {
	return false
}

func (mc modeConstrained) JournalEnabled() bool {
	return true
}

func (mc modeConstrained) UnmergedTLFsEnabled() bool {
	return true
}

func (mc modeConstrained) ServiceKeepaliveEnabled() bool {
	return false
}

func (mc modeConstrained) TLFEditHistoryEnabled() bool {
	return false
}

func (mc modeConstrained) LocalHTTPServerEnabled() bool {
	return true
}

// Wrapper for tests.

type modeTest struct {
	InitMode
}

func (mt modeTest) IsTestMode() bool {
	return true
}
<|endoftext|>


<commit_before>/*
   Copyright 2020 Docker, 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,
   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 compose

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/compose-spec/compose-go/cli"
	"github.com/spf13/cobra"

	"github.com/docker/api/client"
)

func psCommand() *cobra.Command {
	opts := cli.ProjectOptions{}
	psCmd := &cobra.Command{
		Use: "ps",
		RunE: func(cmd *cobra.Command, args []string) error {
			return runPs(cmd.Context(), opts)
		},
	}
	psCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name")
	psCmd.Flags().StringVar(&opts.WorkingDir, "workdir", ".", "Work dir")
	psCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files")

	return psCmd
}

func runPs(ctx context.Context, opts cli.ProjectOptions) error {
	c, err := client.New(ctx)
	if err != nil {
		return err
	}

	composeService := c.ComposeService()
	if composeService == nil {
		return errors.New("compose not implemented in current context")
	}

	serviceList, err := composeService.Ps(ctx, opts)
	if err != nil {
		return err
	}
	printSection(os.Stdout, len(serviceList), func(w io.Writer) {
		for _, service := range serviceList {
			fmt.Fprintf(w, "%s\t%s\t%d/%d\t%s\n", service.ID, service.Name, service.Replicas, service.Desired, strings.Join(service.Ports, ", "))
		}
	}, "ID", "NAME", "REPLICAS", "PORTS")
	return nil
}

func printSection(out io.Writer, len int, printer func(io.Writer), headers ...string) {
	w := tabwriter.NewWriter(out, 20, 1, 3, ' ', 0)
	fmt.Fprintln(w, strings.Join(headers, "\t"))
	printer(w)
	w.Flush()
}
<commit_msg>remove unused parameter<commit_after>/*
   Copyright 2020 Docker, 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,
   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 compose

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/compose-spec/compose-go/cli"
	"github.com/spf13/cobra"

	"github.com/docker/api/client"
)

func psCommand() *cobra.Command {
	opts := cli.ProjectOptions{}
	psCmd := &cobra.Command{
		Use: "ps",
		RunE: func(cmd *cobra.Command, args []string) error {
			return runPs(cmd.Context(), opts)
		},
	}
	psCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name")
	psCmd.Flags().StringVar(&opts.WorkingDir, "workdir", ".", "Work dir")
	psCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files")

	return psCmd
}

func runPs(ctx context.Context, opts cli.ProjectOptions) error {
	c, err := client.New(ctx)
	if err != nil {
		return err
	}

	composeService := c.ComposeService()
	if composeService == nil {
		return errors.New("compose not implemented in current context")
	}

	serviceList, err := composeService.Ps(ctx, opts)
	if err != nil {
		return err
	}
	printSection(os.Stdout, func(w io.Writer) {
		for _, service := range serviceList {
			fmt.Fprintf(w, "%s\t%s\t%d/%d\t%s\n", service.ID, service.Name, service.Replicas, service.Desired, strings.Join(service.Ports, ", "))
		}
	}, "ID", "NAME", "REPLICAS", "PORTS")
	return nil
}

func printSection(out io.Writer, printer func(io.Writer), headers ...string) {
	w := tabwriter.NewWriter(out, 20, 1, 3, ' ', 0)
	fmt.Fprintln(w, strings.Join(headers, "\t"))
	printer(w)
	w.Flush()
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"os"
	"strings"
)

// Share is a command that will display the code in the CLI
type Share struct{}

// Help give a specific instructions about how to use the share command
func (s Share) Help() string {
	text := `
Usage: kode share [filename]

  Share the code and create a URL (so it can be shown in the browser)

filename:

	The file that contains the source code you want to share

Examples:

  $ kode share main.go
  http://koderunr.tech/#zW0CX1qn02
`
	return strings.TrimSpace(text)
}

// ShortDescription give a brief introduction about what share command does.
func (s Share) ShortDescription() string {
	return "kode share [filename] - Share the code by creating a URL"
}

// Exec fetch the share id and compose the uri
func (s Share) Exec(args []string) int {
	runner, err := createRunnerFromArgs(args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		return 1
	}

	url, err := runner.Share()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: Failed to share the code - %v\n", err)
		return 1
	}
	fmt.Println(url)
	return 0
}
<commit_msg>open sare url in browser.<commit_after>package commands

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
)

// Share is a command that will display the code in the CLI
type Share struct{}

// Help give a specific instructions about how to use the share command
func (s Share) Help() string {
	text := `
Usage: kode share [filename]

  Share the code and create a URL (so it can be shown in the browser)

filename:

	The file that contains the source code you want to share

Examples:

  $ kode share main.go
  http://koderunr.tech/#zW0CX1qn02
`
	return strings.TrimSpace(text)
}

// ShortDescription give a brief introduction about what share command does.
func (s Share) ShortDescription() string {
	return "kode share [filename] - Share the code by creating a URL"
}

// Exec fetch the share id and compose the uri
func (s Share) Exec(args []string) int {
	runner, err := createRunnerFromArgs(args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		return 1
	}

	url, err := runner.Share()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: Failed to share the code - %v\n", err)
		return 1
	}

	if isOSDarwin() {
		exec.Command("open", url).Run()

	} else {
		fmt.Println(url)
	}

	return 0
}

func isOSDarwin() bool {
	return runtime.GOOS == "darwin"
}
<|endoftext|>


<commit_before>/*
utils are currently just a wrapper on top of github/segmentio's extremely fast
Camelcase and Snakecase functions, with an added PascalCase.

Thank you @tj for switching to Go just before we did! ;)
*/
package utils

import (
	"errors"
	"reflect"
	"strings"

	"github.com/segmentio/go-camelcase"
	"github.com/segmentio/go-snakecase"
)

func Slug(str string) string {
	return strings.Replace(snakecase.Snakecase(str), "_", "-", -1)
}

func SnakeCase(str string) string {
	return snakecase.Snakecase(str)
}

func CamelCase(str string) string {
	return camelcase.Camelcase(str)
}

func PascalCase(str string) string {
	out := camelcase.Camelcase(str)
	if len(out) > 0 {
		out = strings.ToUpper(out[0:1]) + out[1:len(out)]
	}
	return out
}

// InterfaceToReflect helps ensure the reflect value is in an editable state
// It will check the type and get the correct reference if possible
// @TODO Make some tests
func InterfaceToReflect(val interface{}) (reflectValue reflect.Value, err error) {
	typ := reflect.TypeOf(val)

	// @TODO Is this correct?
	if typ.String() == "reflect.Value" {
		reflectValue = val.(reflect.Value)

	} else if typ.String()[0:1] != "*" {
		err = errors.New("Please provide a reference to the value")
		return

	} else {
		reflectValue = reflect.ValueOf(val).Elem()
	}

	return
}
<commit_msg>Added kebab-case<commit_after>/*
utils are currently just a wrapper on top of github/segmentio's extremely fast
Camelcase and Snakecase functions, with an added PascalCase.

Thank you @tj for switching to Go just before we did! ;)
*/
package utils

import (
	"errors"
	"reflect"
	"strings"

	"github.com/segmentio/go-camelcase"
	"github.com/segmentio/go-snakecase"
)

func Slug(str string) string {
	return strings.Replace(snakecase.Snakecase(str), "_", "-", -1)
}

func SnakeCase(str string) string {
	return snakecase.Snakecase(str)
}

func KebabCase(str string) string {
	return strings.Replace(snakecase.Snakecase(str), "_", "-", -1)
}

func CamelCase(str string) string {
	return camelcase.Camelcase(str)
}

func PascalCase(str string) string {
	out := camelcase.Camelcase(str)
	if len(out) > 0 {
		out = strings.ToUpper(out[0:1]) + out[1:len(out)]
	}
	return out
}

// InterfaceToReflect helps ensure the reflect value is in an editable state
// It will check the type and get the correct reference if possible
// @TODO Make some tests
func InterfaceToReflect(val interface{}) (reflectValue reflect.Value, err error) {
	typ := reflect.TypeOf(val)

	// @TODO Is this correct?
	if typ.String() == "reflect.Value" {
		reflectValue = val.(reflect.Value)

	} else if typ.String()[0:1] != "*" {
		err = errors.New("Please provide a reference to the value")
		return

	} else {
		reflectValue = reflect.ValueOf(val).Elem()
	}

	return
}
<|endoftext|>


<commit_before>package trog

type rawNode struct {
	Id        NodeId
	ParentIds []NodeId // Every ancestor id, all the way up to the root
	ChildIds  []NodeId // Every direct child id of this node
	Pairs     []Pair   // Key/value pairs
	Flags     []Flag   // Value-only flags
}

type Node struct {
	rawNode
	Parents  []*Node // Every ancestor, all the way up to the root
	Children []*Node // Every direct child of this node
}
<commit_msg>Add some basic tree functions<commit_after>package trog

type rawNode struct {
	Id        NodeId
	ParentIds []NodeId // Every ancestor id, all the way up to the root
	ChildIds  []NodeId // Every direct child id of this node
	Parents   []*Node  // Every ancestor, all the way up to the root
	Children  []*Node  // Every direct child of this node
}

type Node struct {
	Pairs    []Pair  // Key/value pairs
	Flags    []Flag  // Value-only flags
	Parent   *Node   // Direct ancestor of this node
	Children []*Node // Direct children of this node
	Parents  []*Node // Every ancestor, all the way up to the root
}

// Create a new, empty, node.
func NewNode() *Node {
	return &Node{}
}

// Add a new node between the given node and its parent.
func (node *Node) Split() *Node {
	newNode := NewNode()
	parent := node.Parent

	if parent != nil {
		parent.delChild(node)
		parent.addChild(newNode)
	}
	newNode.addChild(node)
	return newNode
}

// Add a new child to the given node.
func (node *Node) AddChild() *Node {
	newNode := NewNode()
	node.addChild(newNode)
	return newNode
}

func (node *Node) addChild(child *Node) {
	child.Parent = node
	node.Children = append(node.Children, child)
}

func (node *Node) delChild(child *Node) {
	for i := 0; i < len(node.Children); i++ {
		if node.Children[i] == child {
			node.Children[i] = node.Children[len(node.Children)-1]
			node.Children = node.Children[:len(node.Children)-1]
			child.Parent = nil
		}
	}
}
<|endoftext|>


<commit_before>package dht

import (
	"fmt"
	"log"
	"net"
	"net/http"
	"time"

	"github.com/hashicorp/consul/api"
	"github.com/stvp/rendezvous"
)

const (
	defaultCheckInterval = 5 * time.Second
	pollWait             = time.Second
)

func newCheckListenerAndServer() (listener net.Listener, server *http.Server, err error) {
	listener, err = net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return listener, nil, err
	}

	server = &http.Server{
		ReadTimeout:  time.Second,
		WriteTimeout: time.Second,
		Handler: http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
			fmt.Fprintf(resp, "OK")
		}),
	}

	// When the listener is closed, this goroutine returns.
	go server.Serve(listener)

	return listener, server, err
}

// Node is a single node in a distributed hash table, coordinated using
// services registered in Consul. Key membership is determined using rendezvous
// hashing to ensure even distribution of keys and minimal key membership
// changes when a Node fails or otherwise leaves the hash table.
//
// Errors encountered when making blocking GET requests to the Consul agent API
// are logged using the log package.
type Node struct {
	// Consul
	serviceName string
	serviceID   string
	consul      *api.Client

	// HTTP health check server
	checkURL      string
	checkListener net.Listener
	checkServer   *http.Server

	// Hash table
	hashTable *rendezvous.Table
	waitIndex uint64

	// Graceful shutdown
	stop chan bool
}

// Join creates a new Node and adds it to the distributed hash table specified
// by the given name. The given id should be unique among all Nodes in the hash
// table.
func Join(name, id string) (node *Node, err error) {
	node = &Node{
		serviceName: name,
		serviceID:   id,
		stop:        make(chan bool),
	}

	node.consul, err = api.NewClient(api.DefaultConfig())
	if err != nil {
		return nil, fmt.Errorf("dht: can't create Consul API client: %s", err)
	}

	node.checkListener, node.checkServer, err = newCheckListenerAndServer()
	if err != nil {
		return nil, fmt.Errorf("dht: can't start HTTP server: %s", err)
	}

	err = node.register()
	if err != nil {
		return nil, fmt.Errorf("dht: can't register %s service: %s", node.serviceName, err)
	}

	err = node.update()
	if err != nil {
		return nil, fmt.Errorf("dht: can't fetch %s services list: %s", node.serviceName, err)
	}

	go node.poll()

	return node, nil
}

func (n *Node) register() (err error) {
	err = n.consul.Agent().ServiceRegister(&api.AgentServiceRegistration{
		Name: n.serviceName,
		ID:   n.serviceID,
		Check: &api.AgentServiceCheck{
			HTTP:     fmt.Sprintf("http://%s", n.checkListener.Addr().String()),
			Interval: defaultCheckInterval.String(),
		},
	})
	return err
}

func (n *Node) poll() {
	var err error

	for {
		select {
		case <-n.stop:
			return
		case <-time.After(pollWait):
			err = n.update()
			if err != nil {
				log.Printf("[dht %s %s] error: %s", n.serviceName, n.serviceID, err)
			}
		}
	}
}

// update blocks until the service list changes or until the Consul agent's
// timeout is reached.
func (n *Node) update() (err error) {
	opts := &api.QueryOptions{WaitIndex: n.waitIndex}
	services, meta, err := n.consul.Catalog().Service(n.serviceName, "", opts)
	if err != nil {
		return err
	}

	ids := make([]string, len(services))
	for i, service := range services {
		ids[i] = service.ServiceID
	}

	n.hashTable = rendezvous.New(ids)
	n.waitIndex = meta.LastIndex

	return nil
}

// Member returns true if the given key belongs to this Node in the distributed
// hash table.
func (n *Node) Member(key string) bool {
	return n.hashTable.Get(key) == n.serviceID
}

// Leave removes the Node from the distributed hash table by de-registering it
// from Consul. Once Leave is called, the Node should be discarded. An error is
// returned if the Node is unable to successfully deregister itself from
// Consul. In that case, Consul's health check for the Node will fail and
// require manual cleanup.
func (n *Node) Leave() (err error) {
	close(n.stop) // stop polling for state
	err = n.consul.Agent().ServiceDeregister(n.serviceID)
	n.checkListener.Close() // stop the health check http server
	return err
}
<commit_msg>defaultCheckInterval -> defaultCheck<commit_after>package dht

import (
	"fmt"
	"log"
	"net"
	"net/http"
	"time"

	"github.com/hashicorp/consul/api"
	"github.com/stvp/rendezvous"
)

const (
	checkInterval = 5 * time.Second
	pollWait      = time.Second
)

func newCheckListenerAndServer() (listener net.Listener, server *http.Server, err error) {
	listener, err = net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return listener, nil, err
	}

	server = &http.Server{
		ReadTimeout:  time.Second,
		WriteTimeout: time.Second,
		Handler: http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
			fmt.Fprintf(resp, "OK")
		}),
	}

	// When the listener is closed, this goroutine returns.
	go server.Serve(listener)

	return listener, server, err
}

// Node is a single node in a distributed hash table, coordinated using
// services registered in Consul. Key membership is determined using rendezvous
// hashing to ensure even distribution of keys and minimal key membership
// changes when a Node fails or otherwise leaves the hash table.
//
// Errors encountered when making blocking GET requests to the Consul agent API
// are logged using the log package.
type Node struct {
	// Consul
	serviceName string
	serviceID   string
	consul      *api.Client

	// HTTP health check server
	checkURL      string
	checkListener net.Listener
	checkServer   *http.Server

	// Hash table
	hashTable *rendezvous.Table
	waitIndex uint64

	// Graceful shutdown
	stop chan bool
}

// Join creates a new Node and adds it to the distributed hash table specified
// by the given name. The given id should be unique among all Nodes in the hash
// table.
func Join(name, id string) (node *Node, err error) {
	node = &Node{
		serviceName: name,
		serviceID:   id,
		stop:        make(chan bool),
	}

	node.consul, err = api.NewClient(api.DefaultConfig())
	if err != nil {
		return nil, fmt.Errorf("dht: can't create Consul API client: %s", err)
	}

	node.checkListener, node.checkServer, err = newCheckListenerAndServer()
	if err != nil {
		return nil, fmt.Errorf("dht: can't start HTTP server: %s", err)
	}

	err = node.register()
	if err != nil {
		return nil, fmt.Errorf("dht: can't register %s service: %s", node.serviceName, err)
	}

	err = node.update()
	if err != nil {
		return nil, fmt.Errorf("dht: can't fetch %s services list: %s", node.serviceName, err)
	}

	go node.poll()

	return node, nil
}

func (n *Node) register() (err error) {
	err = n.consul.Agent().ServiceRegister(&api.AgentServiceRegistration{
		Name: n.serviceName,
		ID:   n.serviceID,
		Check: &api.AgentServiceCheck{
			HTTP:     fmt.Sprintf("http://%s", n.checkListener.Addr().String()),
			Interval: checkInterval.String(),
		},
	})
	return err
}

func (n *Node) poll() {
	var err error

	for {
		select {
		case <-n.stop:
			return
		case <-time.After(pollWait):
			err = n.update()
			if err != nil {
				log.Printf("[dht %s %s] error: %s", n.serviceName, n.serviceID, err)
			}
		}
	}
}

// update blocks until the service list changes or until the Consul agent's
// timeout is reached.
func (n *Node) update() (err error) {
	opts := &api.QueryOptions{WaitIndex: n.waitIndex}
	services, meta, err := n.consul.Catalog().Service(n.serviceName, "", opts)
	if err != nil {
		return err
	}

	ids := make([]string, len(services))
	for i, service := range services {
		ids[i] = service.ServiceID
	}

	n.hashTable = rendezvous.New(ids)
	n.waitIndex = meta.LastIndex

	return nil
}

// Member returns true if the given key belongs to this Node in the distributed
// hash table.
func (n *Node) Member(key string) bool {
	return n.hashTable.Get(key) == n.serviceID
}

// Leave removes the Node from the distributed hash table by de-registering it
// from Consul. Once Leave is called, the Node should be discarded. An error is
// returned if the Node is unable to successfully deregister itself from
// Consul. In that case, Consul's health check for the Node will fail and
// require manual cleanup.
func (n *Node) Leave() (err error) {
	close(n.stop) // stop polling for state
	err = n.consul.Agent().ServiceDeregister(n.serviceID)
	n.checkListener.Close() // stop the health check http server
	return err
}
<|endoftext|>


<commit_before>package gorethink

import (
	"sync"
	"sync/atomic"
	"time"

	p "github.com/dancannon/gorethink/ql2"
)

const (
	maxNodeHealth = 100
)

// Node represents a database server in the cluster
type Node struct {
	ID      string
	Host    Host
	aliases []Host

	cluster         *Cluster
	pool            *Pool
	refreshDoneChan chan struct{}

	mu     sync.RWMutex
	closed bool
	health int64
}

func newNode(id string, aliases []Host, cluster *Cluster, pool *Pool) *Node {
	node := &Node{
		ID:              id,
		Host:            aliases[0],
		aliases:         aliases,
		cluster:         cluster,
		pool:            pool,
		health:          maxNodeHealth,
		refreshDoneChan: make(chan struct{}),
	}
	// Start node refresh loop
	refreshInterval := cluster.opts.NodeRefreshInterval
	if refreshInterval <= 0 {
		// Default to refresh every 30 seconds
		refreshInterval = time.Second * 30
	}

	if cluster.opts.DiscoverHosts {
		go func() {
			refreshTicker := time.NewTicker(refreshInterval)
			for {
				select {
				case <-refreshTicker.C:
					node.Refresh()
				case <-node.refreshDoneChan:
					return
				}
			}
		}()
	}

	return node
}

// Closed returns true if the node is closed
func (n *Node) Closed() bool {
	n.mu.RLock()
	defer n.mu.RUnlock()

	return n.closed
}

// Close closes the session
func (n *Node) Close(optArgs ...CloseOpts) error {
	n.mu.Lock()
	defer n.mu.Unlock()

	if n.closed {
		return nil
	}

	if len(optArgs) >= 1 {
		if optArgs[0].NoReplyWait {
			n.NoReplyWait()
		}
	}

	n.refreshDoneChan <- struct{}{}
	if n.pool != nil {
		n.pool.Close()
	}
	n.pool = nil
	n.closed = true

	return nil
}

// SetMaxIdleConns sets the maximum number of connections in the idle
// connection pool.
func (n *Node) SetMaxIdleConns(idleConns int) {
	n.pool.SetMaxIdleConns(idleConns)
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
func (n *Node) SetMaxOpenConns(openConns int) {
	n.pool.SetMaxOpenConns(openConns)
}

// NoReplyWait ensures that previous queries with the noreply flag have been
// processed by the server. Note that this guarantee only applies to queries
// run on the given connection
func (n *Node) NoReplyWait() error {
	return n.pool.Exec(Query{
		Type: p.Query_NOREPLY_WAIT,
	})
}

// Query executes a ReQL query using this nodes connection pool.
func (n *Node) Query(q Query) (cursor *Cursor, err error) {
	if n.Closed() {
		return nil, ErrInvalidNode
	}

	cursor, err = n.pool.Query(q)
	if err != nil {
		n.DecrementHealth()
	}

	return cursor, err
}

// Exec executes a ReQL query using this nodes connection pool.
func (n *Node) Exec(q Query) (err error) {
	if n.Closed() {
		return ErrInvalidNode
	}

	err = n.pool.Exec(q)
	if err != nil {
		n.DecrementHealth()
	}

	return err
}

// Refresh attempts to connect to the node and check that it is still connected
// to the cluster.
//
// If an error occurred or the node is no longer connected then
// the nodes health is decrease, if there were no issues then the node is marked
// as being healthy.
func (n *Node) Refresh() {
	cursor, err := n.pool.Query(newQuery(
		DB("rethinkdb").Table("server_status").Get(n.ID),
		map[string]interface{}{},
		n.cluster.opts,
	))
	if err != nil {
		n.DecrementHealth()
		return
	}
	defer cursor.Close()

	var status nodeStatus
	err = cursor.One(&status)
	if err != nil {
		return
	}

	if status.Status != "connected" {
		n.DecrementHealth()
		return
	}

	// If status check was successful reset health
	n.ResetHealth()
}

// DecrementHealth decreases the nodes health by 1 (the nodes health starts at maxNodeHealth)
func (n *Node) DecrementHealth() {
	if n.cluster.opts.DiscoverHosts {
		atomic.AddInt64(&n.health, -1)
	}
}

// ResetHealth sets the nodes health back to maxNodeHealth (fully healthy)
func (n *Node) ResetHealth() {
	atomic.StoreInt64(&n.health, maxNodeHealth)
}

// IsHealthy checks the nodes health by ensuring that the health counter is above 0.
func (n *Node) IsHealthy() bool {
	return n.health > 0
}

type nodeStatus struct {
	ID      string `gorethink:"id"`
	Name    string `gorethink:"name"`
	Status  string `gorethink:"status"`
	Network struct {
		Hostname           string `gorethink:"hostname"`
		ClusterPort        int64  `gorethink:"cluster_port"`
		ReqlPort           int64  `gorethink:"reql_port"`
		CanonicalAddresses []struct {
			Host string `gorethink:"host"`
			Port int64  `gorethink:"port"`
		} `gorethink:"canonical_addresses"`
	} `gorethink:"network"`
}
<commit_msg>Fixed issue causing infinite blocking by using a simple ping query instead<commit_after>package gorethink

import (
	"sync"
	"sync/atomic"
	"time"

	p "github.com/dancannon/gorethink/ql2"
)

const (
	maxNodeHealth = 100
)

// Node represents a database server in the cluster
type Node struct {
	ID      string
	Host    Host
	aliases []Host

	cluster         *Cluster
	pool            *Pool
	refreshDoneChan chan struct{}

	mu     sync.RWMutex
	closed bool
	health int64
}

func newNode(id string, aliases []Host, cluster *Cluster, pool *Pool) *Node {
	node := &Node{
		ID:              id,
		Host:            aliases[0],
		aliases:         aliases,
		cluster:         cluster,
		pool:            pool,
		health:          maxNodeHealth,
		refreshDoneChan: make(chan struct{}),
	}
	// Start node refresh loop
	refreshInterval := cluster.opts.NodeRefreshInterval
	if refreshInterval <= 0 {
		// Default to refresh every 30 seconds
		refreshInterval = time.Second * 30
	}

	go func() {
		refreshTicker := time.NewTicker(refreshInterval)
		for {
			select {
			case <-refreshTicker.C:
				node.Refresh()
			case <-node.refreshDoneChan:
				return
			}
		}
	}()

	return node
}

// Closed returns true if the node is closed
func (n *Node) Closed() bool {
	n.mu.RLock()
	defer n.mu.RUnlock()

	return n.closed
}

// Close closes the session
func (n *Node) Close(optArgs ...CloseOpts) error {
	n.mu.Lock()
	defer n.mu.Unlock()

	if n.closed {
		return nil
	}

	if len(optArgs) >= 1 {
		if optArgs[0].NoReplyWait {
			n.NoReplyWait()
		}
	}

	n.refreshDoneChan <- struct{}{}
	if n.pool != nil {
		n.pool.Close()
	}
	n.pool = nil
	n.closed = true

	return nil
}

// SetMaxIdleConns sets the maximum number of connections in the idle
// connection pool.
func (n *Node) SetMaxIdleConns(idleConns int) {
	n.pool.SetMaxIdleConns(idleConns)
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
func (n *Node) SetMaxOpenConns(openConns int) {
	n.pool.SetMaxOpenConns(openConns)
}

// NoReplyWait ensures that previous queries with the noreply flag have been
// processed by the server. Note that this guarantee only applies to queries
// run on the given connection
func (n *Node) NoReplyWait() error {
	return n.pool.Exec(Query{
		Type: p.Query_NOREPLY_WAIT,
	})
}

// Query executes a ReQL query using this nodes connection pool.
func (n *Node) Query(q Query) (cursor *Cursor, err error) {
	if n.Closed() {
		return nil, ErrInvalidNode
	}

	cursor, err = n.pool.Query(q)
	if err != nil {
		n.DecrementHealth()
	}

	return cursor, err
}

// Exec executes a ReQL query using this nodes connection pool.
func (n *Node) Exec(q Query) (err error) {
	if n.Closed() {
		return ErrInvalidNode
	}

	err = n.pool.Exec(q)
	if err != nil {
		n.DecrementHealth()
	}

	return err
}

// Refresh attempts to connect to the node and check that it is still connected
// to the cluster.
//
// If an error occurred or the node is no longer connected then
// the nodes health is decrease, if there were no issues then the node is marked
// as being healthy.
func (n *Node) Refresh() {
	if n.cluster.opts.DiscoverHosts {
		// If host discovery is enabled then check the servers status
		cursor, err := n.pool.Query(newQuery(
			DB("rethinkdb").Table("server_status").Get(n.ID),
			map[string]interface{}{},
			n.cluster.opts,
		))
		if err != nil {
			n.DecrementHealth()
			return
		}
		defer cursor.Close()

		var status nodeStatus
		err = cursor.One(&status)
		if err != nil {
			return
		}

		if status.Status != "connected" {
			n.DecrementHealth()
			return
		}
	} else {
		// If host discovery is disabled just execute a simple ping query
		cursor, err := n.pool.Query(newQuery(
			Expr("OK"),
			map[string]interface{}{},
			n.cluster.opts,
		))
		if err != nil {
			n.DecrementHealth()
			return
		}
		defer cursor.Close()

		var status string
		err = cursor.One(&status)
		if err != nil {
			return
		}

		if status != "OK" {
			n.DecrementHealth()
			return
		}
	}

	// If status check was successful reset health
	n.ResetHealth()
}

// DecrementHealth decreases the nodes health by 1 (the nodes health starts at maxNodeHealth)
func (n *Node) DecrementHealth() {
	atomic.AddInt64(&n.health, -1)
}

// ResetHealth sets the nodes health back to maxNodeHealth (fully healthy)
func (n *Node) ResetHealth() {
	atomic.StoreInt64(&n.health, maxNodeHealth)
}

// IsHealthy checks the nodes health by ensuring that the health counter is above 0.
func (n *Node) IsHealthy() bool {
	return n.health > 0
}

type nodeStatus struct {
	ID      string `gorethink:"id"`
	Name    string `gorethink:"name"`
	Status  string `gorethink:"status"`
	Network struct {
		Hostname           string `gorethink:"hostname"`
		ClusterPort        int64  `gorethink:"cluster_port"`
		ReqlPort           int64  `gorethink:"reql_port"`
		CanonicalAddresses []struct {
			Host string `gorethink:"host"`
			Port int64  `gorethink:"port"`
		} `gorethink:"canonical_addresses"`
	} `gorethink:"network"`
}
<|endoftext|>


<commit_before>// (c) Copyright 2015 JONNALAGADDA Srinivas
//
// 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 flow

import "time"

// Node represents some processing or a response to an explicit user
// action.
type Node struct {
	id       uint64
	defn     *NodeDefinition
	workflow *Workflow
	doc      *Document
	resEv    *DocEvent
	resMsg   *Message
}

// newNode creates and initialises a node in the given workflow, as
// per the given node definition.
func newNode(defn *NodeDefinition, wf *Workflow, doc *Document) *Node {
	// WARNING: In a truly busy application, this manner of generating
	// IDs could lead to clashes.
	t := time.Now().UTC().UnixNano()
	return &Node{id: uint64(t), defn: defn, workflow: wf, doc: doc}
}

// Definition answers the node definition of this instance.
func (n *Node) Definition() *NodeDefinition {
	return n.defn
}

// Workflow answers the containing flow of this node.
func (n *Node) Workflow() *Workflow {
	return n.workflow
}

// Document answers the document in this workflow.
func (n *Node) Document() *Document {
	return n.doc
}

// Run processes the document in this node, using the registered
// function and the given parameters.
func (n *Node) Run(args ...interface{}) (*Message, error) {
	ev, msg, err := n.defn.nfunc(n.doc, args...)
	if err != nil {
		return nil, err
	}

	// Needed for recovery.
	n.resEv = ev
	n.resMsg = msg

	// TODO(js): Resolve this.
	// err = n.doc.applyEvent(ev)
	if err != nil {
		return nil, err
	}

	n.workflow.moveToNode(n, msg.node)
	return msg, nil
}

// ResultEvent answers the document event that is the outcome of
// processing in this node, if the processing has already occurred.
func (n *Node) ResultEvent() *DocEvent {
	return n.resEv
}

// ResultMessage answers the message that represents the next step in
// the processing of this workflow, and which is handed over to the
// workflow instance.  This is available only after the processing has
// already occurred.
func (n *Node) ResultMessage() *Message {
	return n.resMsg
}
<commit_msg>Remove `Node` so that `NodeDefinition` can play an active, stateless role<commit_after><|endoftext|>


<commit_before>package main

import (
	goopt "github.com/droundy/goopt"
	"fmt"
	"http"
	"time"
	"strings"
	"os"
	"net"
	"bufio"
	"sort"
	"url"
	)

var Author = "Alexander Solovyov"
var Version = "0.1"
var Summary = "gofigure [OPTS] URL\n"

var reqs = goopt.Int([]string{"-n", "--requests"}, 1,
	"number of requests to make")
var concurrency = goopt.Int([]string{"-c", "--concurrency"}, 1,
	"concurrency level")

type someError struct {
	what string
	str  string
}

func (e *someError) String() string {
	return fmt.Sprintf(e.what, e.str)
}

type result struct {
	time int64
	err os.Error
}

type Int64Array []int64
func (p Int64Array) Len() int           { return len(p) }
func (p Int64Array) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Array) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

func main() {
	goopt.Author = Author
	goopt.Version = Version
	goopt.Summary = Summary
	goopt.Parse(nil)

	if len(goopt.Args) == 0 {
		println(goopt.Usage())
		return
	}

	if *concurrency > *reqs {
		fmt.Printf("You can't have concurrency higher than number of requests\n")
		return
	}

	url, err := getURL(goopt.Args[0])
	if err != nil {
		fmt.Printf("url is invalid: %s\n", err)
		return
	}

	fmt.Printf("Statistics for requests to %s\n", goopt.Args[0])
	results, total := start(url, *reqs, *concurrency)
	printStats(results, total)
}

func start(url *url.URL, requests int, concurrency int) ([]result, int64) {
	results := make([]result, requests)
	queue := make(chan int, requests)
	out := make(chan result, concurrency)
	const fmtCompleted = "\rCompleted %d from %d requests"

	for i := 0; i < requests; i++ {
		queue <- i
	}

	now := time.Nanoseconds()

	for i := 0; i < concurrency; i++ {
		go sender(url, queue, out)
	}

	for i := 0; i < requests; i++ {
		results[i] = <- out

		if i > 0 && i % 10 == 0 {
			fmt.Printf(fmtCompleted, i, requests)
		}
	}

	// erase 'Completed ...' line
	fmt.Printf("\r%*s", len(fmtCompleted), " ")
	return results, time.Nanoseconds() - now
}

func printStats(results []result, workTime int64) {
	times := make(Int64Array, 0)
	total := int64(0)

	for _, r := range(results) {
		if r.err == nil {
			times = append(times, r.time)
			total += r.time
		}
	}
	sort.Sort(times)

	average, median := int64(0), int64(0)
	if len(times) > 0 {
		average = total / int64(len(times))
		median = times[len(times) / 2]
	} else {
		average = 0
		median = 0
	}

	fmt.Printf(`
Total requests performed:       %d
Total failures:                 %d
Time taken for tests:           %.3f ms
Average request takes:          %.3f ms
Median request time:            %.3f ms
Average time between responses: %.3f ms
Average requests per second:    %.3f
`,
		*reqs,
		*reqs - len(times),
		ms(workTime),
		ms(average),
		ms(median),
		ms(workTime / int64(*reqs)),
		(float64(*reqs) / (ms(workTime) / 1000)))
}

func ms(x int64) (float64) {
	return float64(x) / 1000000
}

func hasPort(s string) bool {
	return strings.LastIndex(s, ":") > strings.LastIndex(s, "]")
}

func getURL(rawurl string) (*url.URL, os.Error) {
	URL, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}

	if URL.Scheme != "http" && URL.Scheme != "https" {
		return nil, &someError{"unsupported protocol scheme: %s", URL.Scheme}
	}

	if !hasPort(URL.Host) {
		URL.Host += ":http"
	}

	return URL, nil
}

func sender(url *url.URL, queue chan int, out chan result) {
	for _ = range queue {
		out <- send(url)
	}
}

func send(url *url.URL) result {
	var req http.Request
	req.URL = url

	now := time.Nanoseconds()
	conn, err := net.Dial("tcp", req.URL.Host)
	if err != nil {
		return result{0, err}
	}

	err = req.Write(conn)
	if err != nil {
		conn.Close()
		return result{0, err}
	}

	reader := bufio.NewReader(conn)
	response, err := http.ReadResponse(reader, &req)
	res := result{time.Nanoseconds() - now, err}

	conn.Close()
	response.Body.Close()
	return res
}
<commit_msg>make report every 100 requests and erase more than len(fmt)<commit_after>package main

import (
	goopt "github.com/droundy/goopt"
	"fmt"
	"http"
	"time"
	"strings"
	"os"
	"net"
	"bufio"
	"sort"
	"url"
	)

var Author = "Alexander Solovyov"
var Version = "0.1"
var Summary = "gofigure [OPTS] URL\n"

var reqs = goopt.Int([]string{"-n", "--requests"}, 1,
	"number of requests to make")
var concurrency = goopt.Int([]string{"-c", "--concurrency"}, 1,
	"concurrency level")

type someError struct {
	what string
	str  string
}

func (e *someError) String() string {
	return fmt.Sprintf(e.what, e.str)
}

type result struct {
	time int64
	err os.Error
}

type Int64Array []int64
func (p Int64Array) Len() int           { return len(p) }
func (p Int64Array) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Array) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

func main() {
	goopt.Author = Author
	goopt.Version = Version
	goopt.Summary = Summary
	goopt.Parse(nil)

	if len(goopt.Args) == 0 {
		println(goopt.Usage())
		return
	}

	if *concurrency > *reqs {
		fmt.Printf("You can't have concurrency higher than number of requests\n")
		return
	}

	url, err := getURL(goopt.Args[0])
	if err != nil {
		fmt.Printf("url is invalid: %s\n", err)
		return
	}

	fmt.Printf("Statistics for requests to %s\n", goopt.Args[0])
	results, total := start(url, *reqs, *concurrency)
	printStats(results, total)
}

func start(url *url.URL, requests int, concurrency int) ([]result, int64) {
	results := make([]result, requests)
	queue := make(chan int, requests)
	out := make(chan result, concurrency)
	const fmtCompleted = "\rCompleted %d from %d requests"

	for i := 0; i < requests; i++ {
		queue <- i
	}

	now := time.Nanoseconds()

	for i := 0; i < concurrency; i++ {
		go sender(url, queue, out)
	}

	for i := 0; i < requests; i++ {
		results[i] = <- out

		if i > 0 && i % 100 == 0 {
			fmt.Printf(fmtCompleted, i, requests)
		}
	}

	// erase 'Completed ...' line
	fmt.Printf("\r%*s", len(fmtCompleted) + 10, " ")
	return results, time.Nanoseconds() - now
}

func printStats(results []result, workTime int64) {
	times := make(Int64Array, 0)
	total := int64(0)

	for _, r := range(results) {
		if r.err == nil {
			times = append(times, r.time)
			total += r.time
		}
	}
	sort.Sort(times)

	average, median := int64(0), int64(0)
	if len(times) > 0 {
		average = total / int64(len(times))
		median = times[len(times) / 2]
	} else {
		average = 0
		median = 0
	}

	fmt.Printf(`
Total requests performed:       %d
Total failures:                 %d
Time taken for tests:           %.3f ms
Average request takes:          %.3f ms
Median request time:            %.3f ms
Average time between responses: %.3f ms
Average requests per second:    %.3f
`,
		*reqs,
		*reqs - len(times),
		ms(workTime),
		ms(average),
		ms(median),
		ms(workTime / int64(*reqs)),
		(float64(*reqs) / (ms(workTime) / 1000)))
}

func ms(x int64) (float64) {
	return float64(x) / 1000000
}

func hasPort(s string) bool {
	return strings.LastIndex(s, ":") > strings.LastIndex(s, "]")
}

func getURL(rawurl string) (*url.URL, os.Error) {
	URL, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}

	if URL.Scheme != "http" && URL.Scheme != "https" {
		return nil, &someError{"unsupported protocol scheme: %s", URL.Scheme}
	}

	if !hasPort(URL.Host) {
		URL.Host += ":http"
	}

	return URL, nil
}

func sender(url *url.URL, queue chan int, out chan result) {
	for _ = range queue {
		out <- send(url)
	}
}

func send(url *url.URL) result {
	var req http.Request
	req.URL = url

	now := time.Nanoseconds()
	conn, err := net.Dial("tcp", req.URL.Host)
	if err != nil {
		return result{0, err}
	}

	err = req.Write(conn)
	if err != nil {
		conn.Close()
		return result{0, err}
	}

	reader := bufio.NewReader(conn)
	response, err := http.ReadResponse(reader, &req)
	res := result{time.Nanoseconds() - now, err}

	conn.Close()
	response.Body.Close()
	return res
}
<|endoftext|>


<commit_before>package library

import (
	"os"
	"path/filepath"

	"github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
	"github.com/yuin/gopher-lua"
)

var RBXMK = rbxmk.Library{
	Name: "rbxmk",
	Open: func(s rbxmk.State) *lua.LTable {
		lib := s.L.CreateTable(0, 7)
		lib.RawSetString("load", s.WrapFunc(rbxmkLoad))
		lib.RawSetString("meta", s.WrapFunc(rbxmkMeta))
		lib.RawSetString("newDesc", s.WrapFunc(rbxmkNewDesc))
		lib.RawSetString("encodeFormat", s.WrapFunc(rbxmkEncodeFormat))
		lib.RawSetString("decodeFormat", s.WrapFunc(rbxmkDecodeFormat))
		lib.RawSetString("readSource", s.WrapFunc(rbxmkReadSource))
		lib.RawSetString("writeSource", s.WrapFunc(rbxmkWriteSource))

		mt := s.L.CreateTable(0, 2)
		mt.RawSetString("__index", s.WrapFunc(func(s rbxmk.State) int {
			if field := s.Pull(2, "string").(types.String); field != "desc" {
				s.L.RaiseError("unknown field %q", field)
			}
			desc := s.Desc(nil)
			return s.Push(rtypes.RootDesc{Root: desc})
		}))
		mt.RawSetString("__newindex", s.WrapFunc(func(s rbxmk.State) int {
			if field := s.Pull(2, "string").(types.String); field != "desc" {
				s.L.RaiseError("unknown field %q", field)
			}
			desc := s.PullOpt(3, "RootDesc", nil)
			if desc == nil {
				s.SetDesc(nil)
			}
			s.SetDesc(desc.(rtypes.RootDesc).Root)
			return 0
		}))
		s.L.SetMetatable(lib, mt)

		return lib
	},
}

func rbxmkLoad(s rbxmk.State) int {
	fileName := filepath.Clean(s.L.CheckString(1))
	fi, err := os.Stat(fileName)
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	if err = s.PushFile(rbxmk.FileInfo{Path: fileName, FileInfo: fi}); err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}

	// Load file as function.
	fn, err := s.L.LoadFile(fileName)
	if err != nil {
		s.PopFile()
		s.L.RaiseError(err.Error())
		return 0
	}
	s.L.Push(fn) // +function

	// Push extra arguments as arguments to loaded function.
	nt := s.L.GetTop()
	for i := 2; i <= nt; i++ {
		s.L.Push(s.L.Get(i)) // function, ..., +arg
	}
	// function, +args...

	// Call loaded function.
	err = s.L.PCall(nt-1, lua.MultRet, nil) // -function, -args..., +returns...
	s.PopFile()
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.L.GetTop() - 1
}

func metaGet(s rbxmk.State, inst *rtypes.Instance, name string) int {
	switch name {
	case "Reference":
		return s.Push(types.String(inst.Reference))
	case "IsService":
		return s.Push(types.Bool(inst.IsService))
	default:
		s.L.RaiseError("unknown metadata %q", name)
	}
	return 0
}

func metaSet(s rbxmk.State, inst *rtypes.Instance, name string) int {
	switch name {
	case "Reference":
		inst.Reference = string(s.Pull(3, "string").(types.String))
	case "IsService":
		inst.IsService = bool(s.Pull(3, "bool").(types.Bool))
	default:
		s.L.RaiseError("unknown metadata %q", name)
	}
	return 0
}

func rbxmkMeta(s rbxmk.State) int {
	inst := s.Pull(1, "Instance").(*rtypes.Instance)
	name := string(s.Pull(2, "string").(types.String))
	if s.Count() == 3 {
		return metaSet(s, inst, name)
	}
	return metaGet(s, inst, name)
}

func rbxmkNewDesc(s rbxmk.State) int {
	switch name := string(s.Pull(1, "string").(types.String)); name {
	case "Root":
		return s.Push(rtypes.RootDesc{})
	case "Class":
		return s.Push(rtypes.ClassDesc{})
	case "Property":
		return s.Push(rtypes.PropertyDesc{})
	case "Function":
		return s.Push(rtypes.FunctionDesc{})
	case "Event":
		return s.Push(rtypes.EventDesc{})
	case "Callback":
		return s.Push(rtypes.CallbackDesc{})
	case "Parameter":
		return s.Push(rtypes.ParameterDesc{})
	case "Type":
		return s.Push(rtypes.TypeDesc{})
	case "Enum":
		return s.Push(rtypes.EnumDesc{})
	case "EnumItem":
		return s.Push(rtypes.EnumItemDesc{})
	default:
		s.L.RaiseError("unable to create descriptor of type %q", name)
		return 0
	}
}

func rbxmkEncodeFormat(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	format := s.Format(name)
	if format.Name == "" {
		s.L.RaiseError("unknown format %q", name)
		return 0
	}
	if format.Encode == nil {
		s.L.RaiseError("cannot encode with format %s", name)
		return 0
	}
	b, err := format.Encode(s.Pull(2, "Variant"))
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.Push(types.BinaryString(b))
}

func rbxmkDecodeFormat(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	format := s.Format(name)
	if format.Name == "" {
		s.L.RaiseError("unknown format %q", name)
		return 0
	}
	if format.Decode == nil {
		s.L.RaiseError("cannot decode with format %s", name)
		return 0
	}
	v, err := format.Decode([]byte(s.Pull(2, "BinaryString").(types.BinaryString)))
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.Push(v)
}

func rbxmkReadSource(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	source := s.Source(name)
	if source.Name == "" {
		s.L.RaiseError("unknown source %q", name)
		return 0
	}
	if source.Read == nil {
		s.L.RaiseError("cannot read with format %s", name)
		return 0
	}
	options := make([]interface{}, s.L.GetTop()-1)
	for i := 2; i <= s.L.GetTop(); i++ {
		options[i-2] = s.Pull(i, "Variant")
	}
	b, err := source.Read(options...)
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.Push(types.BinaryString(b))
}

func rbxmkWriteSource(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	source := s.Source(name)
	if source.Name == "" {
		s.L.RaiseError("unknown source %q", name)
		return 0
	}
	if source.Write == nil {
		s.L.RaiseError("cannot write with format %s", name)
		return 0
	}
	b := []byte(s.Pull(2, "BinaryString").(types.BinaryString))
	options := make([]interface{}, s.L.GetTop()-2)
	for i := 3; i <= s.L.GetTop(); i++ {
		options[i-3] = s.Pull(i, "Variant")
	}
	if err := source.Write(b, options...); err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return 0
}
<commit_msg>Fix initialization of descriptor types.<commit_after>package library

import (
	"os"
	"path/filepath"

	"github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
	"github.com/yuin/gopher-lua"
)

var RBXMK = rbxmk.Library{
	Name: "rbxmk",
	Open: func(s rbxmk.State) *lua.LTable {
		lib := s.L.CreateTable(0, 7)
		lib.RawSetString("load", s.WrapFunc(rbxmkLoad))
		lib.RawSetString("meta", s.WrapFunc(rbxmkMeta))
		lib.RawSetString("newDesc", s.WrapFunc(rbxmkNewDesc))
		lib.RawSetString("encodeFormat", s.WrapFunc(rbxmkEncodeFormat))
		lib.RawSetString("decodeFormat", s.WrapFunc(rbxmkDecodeFormat))
		lib.RawSetString("readSource", s.WrapFunc(rbxmkReadSource))
		lib.RawSetString("writeSource", s.WrapFunc(rbxmkWriteSource))

		mt := s.L.CreateTable(0, 2)
		mt.RawSetString("__index", s.WrapFunc(func(s rbxmk.State) int {
			if field := s.Pull(2, "string").(types.String); field != "desc" {
				s.L.RaiseError("unknown field %q", field)
			}
			desc := s.Desc(nil)
			return s.Push(rtypes.RootDesc{Root: desc})
		}))
		mt.RawSetString("__newindex", s.WrapFunc(func(s rbxmk.State) int {
			if field := s.Pull(2, "string").(types.String); field != "desc" {
				s.L.RaiseError("unknown field %q", field)
			}
			desc := s.PullOpt(3, "RootDesc", nil)
			if desc == nil {
				s.SetDesc(nil)
			}
			s.SetDesc(desc.(rtypes.RootDesc).Root)
			return 0
		}))
		s.L.SetMetatable(lib, mt)

		return lib
	},
}

func rbxmkLoad(s rbxmk.State) int {
	fileName := filepath.Clean(s.L.CheckString(1))
	fi, err := os.Stat(fileName)
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	if err = s.PushFile(rbxmk.FileInfo{Path: fileName, FileInfo: fi}); err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}

	// Load file as function.
	fn, err := s.L.LoadFile(fileName)
	if err != nil {
		s.PopFile()
		s.L.RaiseError(err.Error())
		return 0
	}
	s.L.Push(fn) // +function

	// Push extra arguments as arguments to loaded function.
	nt := s.L.GetTop()
	for i := 2; i <= nt; i++ {
		s.L.Push(s.L.Get(i)) // function, ..., +arg
	}
	// function, +args...

	// Call loaded function.
	err = s.L.PCall(nt-1, lua.MultRet, nil) // -function, -args..., +returns...
	s.PopFile()
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.L.GetTop() - 1
}

func metaGet(s rbxmk.State, inst *rtypes.Instance, name string) int {
	switch name {
	case "Reference":
		return s.Push(types.String(inst.Reference))
	case "IsService":
		return s.Push(types.Bool(inst.IsService))
	default:
		s.L.RaiseError("unknown metadata %q", name)
	}
	return 0
}

func metaSet(s rbxmk.State, inst *rtypes.Instance, name string) int {
	switch name {
	case "Reference":
		inst.Reference = string(s.Pull(3, "string").(types.String))
	case "IsService":
		inst.IsService = bool(s.Pull(3, "bool").(types.Bool))
	default:
		s.L.RaiseError("unknown metadata %q", name)
	}
	return 0
}

func rbxmkMeta(s rbxmk.State) int {
	inst := s.Pull(1, "Instance").(*rtypes.Instance)
	name := string(s.Pull(2, "string").(types.String))
	if s.Count() == 3 {
		return metaSet(s, inst, name)
	}
	return metaGet(s, inst, name)
}

func rbxmkNewDesc(s rbxmk.State) int {
	switch name := string(s.Pull(1, "string").(types.String)); name {
	case "Root":
		return s.Push(rtypes.RootDesc{Root: &rbxdump.Root{
			Classes: make(map[string]*rbxdump.Class),
			Enums:   make(map[string]*rbxdump.Enum),
		}})
	case "Class":
		return s.Push(rtypes.ClassDesc{Class: &rbxdump.Class{
			Members: make(map[string]rbxdump.Member),
		}})
	case "Property":
		return s.Push(rtypes.PropertyDesc{Property: &rbxdump.Property{}})
	case "Function":
		return s.Push(rtypes.FunctionDesc{Function: &rbxdump.Function{}})
	case "Event":
		return s.Push(rtypes.EventDesc{Event: &rbxdump.Event{}})
	case "Callback":
		return s.Push(rtypes.CallbackDesc{Callback: &rbxdump.Callback{}})
	case "Parameter":
		return s.Push(rtypes.ParameterDesc{Parameter: &rbxdump.Parameter{}})
	case "Type":
		return s.Push(rtypes.TypeDesc{Embedded: &rbxdump.Type{}})
	case "Enum":
		return s.Push(rtypes.EnumDesc{Enum: &rbxdump.Enum{
			Items: make(map[string]*rbxdump.EnumItem),
		}})
	case "EnumItem":
		return s.Push(rtypes.EnumItemDesc{EnumItem: &rbxdump.EnumItem{}})
	default:
		s.L.RaiseError("unable to create descriptor of type %q", name)
		return 0
	}
}

func rbxmkEncodeFormat(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	format := s.Format(name)
	if format.Name == "" {
		s.L.RaiseError("unknown format %q", name)
		return 0
	}
	if format.Encode == nil {
		s.L.RaiseError("cannot encode with format %s", name)
		return 0
	}
	b, err := format.Encode(s.Pull(2, "Variant"))
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.Push(types.BinaryString(b))
}

func rbxmkDecodeFormat(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	format := s.Format(name)
	if format.Name == "" {
		s.L.RaiseError("unknown format %q", name)
		return 0
	}
	if format.Decode == nil {
		s.L.RaiseError("cannot decode with format %s", name)
		return 0
	}
	v, err := format.Decode([]byte(s.Pull(2, "BinaryString").(types.BinaryString)))
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.Push(v)
}

func rbxmkReadSource(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	source := s.Source(name)
	if source.Name == "" {
		s.L.RaiseError("unknown source %q", name)
		return 0
	}
	if source.Read == nil {
		s.L.RaiseError("cannot read with format %s", name)
		return 0
	}
	options := make([]interface{}, s.L.GetTop()-1)
	for i := 2; i <= s.L.GetTop(); i++ {
		options[i-2] = s.Pull(i, "Variant")
	}
	b, err := source.Read(options...)
	if err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return s.Push(types.BinaryString(b))
}

func rbxmkWriteSource(s rbxmk.State) int {
	name := string(s.Pull(1, "string").(types.String))
	source := s.Source(name)
	if source.Name == "" {
		s.L.RaiseError("unknown source %q", name)
		return 0
	}
	if source.Write == nil {
		s.L.RaiseError("cannot write with format %s", name)
		return 0
	}
	b := []byte(s.Pull(2, "BinaryString").(types.BinaryString))
	options := make([]interface{}, s.L.GetTop()-2)
	for i := 3; i <= s.L.GetTop(); i++ {
		options[i-3] = s.Pull(i, "Variant")
	}
	if err := source.Write(b, options...); err != nil {
		s.L.RaiseError(err.Error())
		return 0
	}
	return 0
}
<|endoftext|>


<commit_before>package main

import (
	"./exporter"
	"./external"
	"./model"
	"./parser"
	"./util"
	"fmt"
	"os"
)

func main() {
	var fp *os.File
	var err error

	// パース対象の xml ファイル名を引数に受ける
	fp, err = os.Open(os.Args[1])
	util.FailOnError(err)
	defer fp.Close()

	var playDataList []model.Playdata
	playDataList = parser.ItunesXmlParse(fp)

	// 出力する csv ファイル名として用いるために、xml ファイルの最終更新日時を取得
	mod_date := util.GetModDate(fp)

	exporter.ExportCsv(mod_date, playDataList)

	//外部コマンドを実行し、プロジェクト名を取得する
	project_name := external.GetProjectName()
	fmt.Println("project_name:", string(project_name))
	//バケットが既に作成済みかどうかを調べて、未作成なら作成する
	if external.IsBucketExists(project_name) {
		fmt.Println("バケット作成済み")
	} else {
		fmt.Println("バケット未作成")
		external.MakeBucket(project_name)
		fmt.Println("バケット作成完了")
	}
	//作成したcsvファイルをアップロード
	external.FileUpload(project_name, mod_date)
	fmt.Println("gcsへのアップロードを完了")
	//BigQueryにデータセットが作成済みかどうかを調べて、未作成なら作成する
	if external.IsDatasetExists(project_name) {
		fmt.Println("データセット作成済み")
	} else {
		fmt.Println("データセット未作成")
		external.MakeDataset(project_name)
		fmt.Println("データセット作成完了")
	}
	//データセット内に既にテーブルがあるかどうかを調べ、なかったときだけロードを実施する（追記されてしまうため）
	if external.IsTableExists(project_name, mod_date) {
		fmt.Println("当該データロード済み")
	} else {
		fmt.Println("当該データ未ロード")
		//作成したデータセットにデータをロードする
		external.LoadToTable(project_name, mod_date)
		fmt.Println("bqへのロードを完了")
	}
	//ロードに使用したcsvファイルをgcsから削除する
	external.RemoveUploadFile(project_name, mod_date)
	fmt.Println("gcs上のファイルの削除を完了")
}
<commit_msg>ログ出力増々で<commit_after>package main

import (
	"./exporter"
	"./external"
	"./model"
	"./parser"
	"./util"
	"fmt"
	"os"
)

func main() {
	fmt.Println("Starting goramoph.")
	var fp *os.File
	var err error

	// パース対象の xml ファイル名を引数に受ける
	fmt.Printf("xml parsing...")
	fp, err = os.Open(os.Args[1])
	util.FailOnError(err)
	defer fp.Close()

	var playDataList []model.Playdata
	playDataList = parser.ItunesXmlParse(fp)

	// 出力する csv ファイル名として用いるために、xml ファイルの最終更新日時を取得
	mod_date := util.GetModDate(fp)
	fmt.Println("done")

	fmt.Printf("exporting csv...")
	exporter.ExportCsv(mod_date, playDataList)
	fmt.Println("done")

	//外部コマンドを実行し、プロジェクト名を取得する
	fmt.Printf("getting Google Cloud Project name...")
	project_name := external.GetProjectName()
	fmt.Println("project_name:", string(project_name))
	//バケットが既に作成済みかどうかを調べて、未作成なら作成する
	fmt.Printf("checking bucket...")
	if external.IsBucketExists(project_name) {
		fmt.Println("bucket has alredy created")
	} else {
		fmt.Printf("bucket has not created yet, now creating...")
		external.MakeBucket(project_name)
		fmt.Println("done")
	}
	//作成したcsvファイルをアップロード
	fmt.Printf("uploading csv...")
	external.FileUpload(project_name, mod_date)
	fmt.Println("done")
	//BigQueryにデータセットが作成済みかどうかを調べて、未作成なら作成する
	fmt.Printf("checking dataset...")
	if external.IsDatasetExists(project_name) {
		fmt.Println("dataset has alredy created")
	} else {
		fmt.Printf("dataset has not created yet, now creating...")
		external.MakeDataset(project_name)
		fmt.Println("done")
	}
	//データセット内に既にテーブルがあるかどうかを調べ、なかったときだけロードを実施する（追記されてしまうため）
	fmt.Printf("checking table...")
	if external.IsTableExists(project_name, mod_date) {
		fmt.Println("this playdata has alredy loaded")
	} else {
		fmt.Printf("this playdata has not load yet, now loading...")
		//作成したデータセットにデータをロードする
		external.LoadToTable(project_name, mod_date)
		fmt.Println("load to table success")
	}
	//ロードに使用したcsvファイルをgcsから削除する
	fmt.Printf("remove csv file on Cloud Storage...")
	external.RemoveUploadFile(project_name, mod_date)
	fmt.Println("done")
	fmt.Println("completed.")
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/xml"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

func EscapeText(text string) string {
	buf := new(bytes.Buffer)
	xml.EscapeText(buf, []byte(text))
	return buf.String()
}

func DataRace(logPath string) {
	writer := bufio.NewWriter(os.Stdout)

	buf := new(bytes.Buffer)
	err := filepath.Walk(filepath.Dir(logPath), func(path string, info os.FileInfo, err error) error {
		if err == nil && !info.IsDir() && strings.HasPrefix(path, logPath) {
			bytes, err := ioutil.ReadFile(path)
			if err != nil {
				log.Fatal(err)
			}
			buf.Write(bytes)
			buf.WriteString("\n")
			buf.WriteString("\n")
		}
		return err
	})
	if err != nil {
		log.Fatal(err)
	}

	writer.WriteString(`<!DOCTYPE html><html><head lang="en"><meta charset="UTF-8"><title>Data race report</title></head><body><pre>`)
	writer.WriteString("\n")
	writer.WriteString(EscapeText(buf.String()))
	writer.WriteString("\n")
	writer.WriteString(`</pre></body></html>`)

	if err := writer.Flush(); err != nil {
		log.Fatal(err)
	}
}

func ErrCheck(inFilePath string) {
	// go get github.com/kisielk/errcheck
	// errcheck ./...

	inFile, err := os.Open(inFilePath)
	if err != nil {
		log.Fatal(err)
	}
	defer inFile.Close()

	writer := bufio.NewWriter(os.Stdout)

	writer.WriteString(`<checkstyle version="4.3">`)
	writer.WriteString("\n")
	scanner := bufio.NewScanner(inFile)
	var prevFileName string
	for scanner.Scan() {
		origLine := scanner.Text()
		line := origLine
		index := strings.Index(line, "\t")
		if index == -1 {
			log.Fatalf(`Could not parse line "%s"`, origLine)
		}
		message := line[index+1:]
		line = line[:index]
		index1 := strings.Index(line, ":")
		index2 := strings.LastIndex(line, ":")
		if index1 == -1 || index2 == -1 {
			log.Fatalf(`Could not parse line "%s"`, origLine)
		}
		fileName := line[:index1]
		lineNumber := line[index1+1 : index2]
		columnNumber := line[index2+1:]

		if prevFileName != fileName {
			if prevFileName != "" {
				writer.WriteString("\t</file>\n")
			}
			writer.WriteString("\t")
			writer.WriteString(fmt.Sprintf(`<file name="%s">`, EscapeText(fileName)))
			writer.WriteString("\n")
		}
		writer.WriteString("\t\t")
		writer.WriteString(fmt.Sprintf(`<error line="%s" column="%s" severity="warning" message="%s"></error>`, lineNumber, columnNumber, EscapeText(message)))
		writer.WriteString("\n")

		prevFileName = fileName
	}
	if prevFileName != "" {
		writer.WriteString("\t</file>\n")
	}
	writer.WriteString("</checkstyle>\n")

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	if err := writer.Flush(); err != nil {
		log.Fatal(err)
	}
}

func Vet(inFilePath string) {
	inFile, err := os.Open(inFilePath)
	if err != nil {
		log.Fatal(err)
	}
	defer inFile.Close()

	writer := bufio.NewWriter(os.Stdout)

	writer.WriteString(`<checkstyle version="4.3">`)
	writer.WriteString("\n")
	scanner := bufio.NewScanner(inFile)
	var prevFileName string
	for scanner.Scan() {
		origLine := scanner.Text()
		line := origLine
        if strings.Index(line, "exit status") != -1 { continue }
		index := strings.Index(line, ": ")
		if index == -1 {
			log.Fatalf(`Could not parse line "%s"`, origLine)
		}
		message := line[index+2:]
		line = line[:index]
		index = strings.LastIndex(line, ":")
		if index == -1 {
			log.Fatalf(`Could not parse line "%s"`, origLine)
		}
		fileName := line[:index]
		lineNumber := line[index+1:]

		if prevFileName != fileName {
			if prevFileName != "" {
				writer.WriteString("\t</file>\n")
			}
			writer.WriteString("\t")
			writer.WriteString(fmt.Sprintf(`<file name="%s">`, EscapeText(fileName)))
			writer.WriteString("\n")
		}
		writer.WriteString("\t\t")
		writer.WriteString(fmt.Sprintf(`<error line="%s" column="1" severity="warning" message="%s"></error>`, lineNumber, EscapeText(message)))
		writer.WriteString("\n")

		prevFileName = fileName
	}
	if prevFileName != "" {
		writer.WriteString("\t</file>\n")
	}
	writer.WriteString("</checkstyle>\n")

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	if err := writer.Flush(); err != nil {
		log.Fatal(err)
	}
}

func main() {
	// /Users/akorzhevskii/Downloads/reports/report
	logPath := flag.String("log_path", "", "go -race log path")
	// /Users/akorzhevskii/Downloads/errcheck.out
	errcheckReport := flag.String("errcheck", "", "errcheck report")
	// /Users/akorzhevskii/Downloads/govet.out
	vetReport := flag.String("vet", "", "go vet report")
	flag.Parse()

	if *logPath != "" {
		DataRace(*logPath)
		return
	}

	if *errcheckReport != "" {
		ErrCheck(*errcheckReport)
		return
	}

	if *vetReport != "" {
		Vet(*vetReport)
		return
	}
}
<commit_msg>exit status fix<commit_after>temp
<|endoftext|>


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

package pd

import (
	"context"
	"testing"
	"time"

	. "github.com/pingcap/check"
	"github.com/pingcap/errors"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/tikv/pd/pkg/testutil"
	"go.uber.org/goleak"
	"google.golang.org/grpc"
)

func Test(t *testing.T) {
	TestingT(t)
}

func TestMain(m *testing.M) {
	goleak.VerifyTestMain(m, testutil.LeakOptions...)
}

var _ = Suite(&testClientSuite{})

type testClientSuite struct{}

func (s *testClientSuite) TestTsLessEqual(c *C) {
	c.Assert(tsLessEqual(9, 9, 9, 9), IsTrue)
	c.Assert(tsLessEqual(8, 9, 9, 8), IsTrue)
	c.Assert(tsLessEqual(9, 8, 8, 9), IsFalse)
	c.Assert(tsLessEqual(9, 8, 9, 6), IsFalse)
	c.Assert(tsLessEqual(9, 6, 9, 8), IsTrue)
}

func (s *testClientSuite) TestUpdateURLs(c *C) {
	members := []*pdpb.Member{
		{Name: "pd4", ClientUrls: []string{"tmp//pd4"}},
		{Name: "pd1", ClientUrls: []string{"tmp//pd1"}},
		{Name: "pd3", ClientUrls: []string{"tmp//pd3"}},
		{Name: "pd2", ClientUrls: []string{"tmp//pd2"}},
	}
	getURLs := func(ms []*pdpb.Member) (urls []string) {
		for _, m := range ms {
			urls = append(urls, m.GetClientUrls()[0])
		}
		return
	}
	cli := &baseClient{}
	cli.updateURLs(members[1:])
	c.Assert(cli.urls, DeepEquals, getURLs([]*pdpb.Member{members[1], members[3], members[2]}))
	cli.updateURLs(members[1:])
	c.Assert(cli.urls, DeepEquals, getURLs([]*pdpb.Member{members[1], members[3], members[2]}))
	cli.updateURLs(members)
	c.Assert(cli.urls, DeepEquals, getURLs([]*pdpb.Member{members[1], members[3], members[2], members[0]}))
}

var _ = Suite(&testClientCtxSuite{})

type testClientCtxSuite struct{}

func (s *testClientCtxSuite) TestClientCtx(c *C) {
	start := time.Now()
	ctx, cancel := context.WithTimeout(context.TODO(), time.Second*3)
	defer cancel()
	_, err := NewClientWithContext(ctx, []string{"localhost:8080"}, SecurityOption{})
	c.Assert(err, NotNil)
	c.Assert(time.Since(start), Less, time.Second*4)
}

func (s *testClientCtxSuite) TestClientWithRetry(c *C) {
	start := time.Now()
	_, err := NewClientWithContext(context.TODO(), []string{"localhost:8080"}, SecurityOption{}, WithMaxErrorRetry(5))
	c.Assert(err, NotNil)
	c.Assert(time.Since(start), Less, time.Second*6)
}

var _ = Suite(&testClientDialOptionSuite{})

type testClientDialOptionSuite struct{}

func (s *testClientDialOptionSuite) TestGRPCDialOption(c *C) {
	start := time.Now()
	ctx, cancel := context.WithTimeout(context.TODO(), 500*time.Millisecond)
	defer cancel()
	// nolint
	cli := &baseClient{
		urls:                 []string{"localhost:8080"},
		checkLeaderCh:        make(chan struct{}, 1),
		checkTSODispatcherCh: make(chan struct{}, 1),
		ctx:                  ctx,
		cancel:               cancel,
		security:             SecurityOption{},
		gRPCDialOptions:      []grpc.DialOption{grpc.WithBlock()},
	}

	err := cli.updateMember()
	c.Assert(err, NotNil)
	c.Assert(time.Since(start), Greater, 500*time.Millisecond)
}

var _ = Suite(&testTsoRequestSuite{})

type testTsoRequestSuite struct{}

func (s *testTsoRequestSuite) TestTsoRequestWait(c *C) {
	ctx, cancel := context.WithCancel(context.Background())
	req := &tsoRequest{
		done:       make(chan error, 1),
		physical:   0,
		logical:    0,
		requestCtx: context.TODO(),
		clientCtx:  ctx,
	}
	cancel()
	_, _, err := req.Wait()
	c.Assert(errors.Cause(err), Equals, context.Canceled)

	ctx, cancel = context.WithCancel(context.Background())
	req = &tsoRequest{
		done:       make(chan error, 1),
		physical:   0,
		logical:    0,
		requestCtx: ctx,
		clientCtx:  context.TODO(),
	}
	cancel()
	_, _, err = req.Wait()
	c.Assert(errors.Cause(err), Equals, context.Canceled)
}
<commit_msg>client: fix the goroutine leak of client unit test (#3574)<commit_after>// Copyright 2016 TiKV Project 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package pd

import (
	"context"
	"testing"
	"time"

	. "github.com/pingcap/check"
	"github.com/pingcap/errors"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/tikv/pd/pkg/testutil"
	"go.uber.org/goleak"
	"google.golang.org/grpc"
)

func Test(t *testing.T) {
	TestingT(t)
}

func TestMain(m *testing.M) {
	goleak.VerifyTestMain(m, testutil.LeakOptions...)
}

var _ = Suite(&testClientSuite{})

type testClientSuite struct{}

func (s *testClientSuite) TestTsLessEqual(c *C) {
	c.Assert(tsLessEqual(9, 9, 9, 9), IsTrue)
	c.Assert(tsLessEqual(8, 9, 9, 8), IsTrue)
	c.Assert(tsLessEqual(9, 8, 8, 9), IsFalse)
	c.Assert(tsLessEqual(9, 8, 9, 6), IsFalse)
	c.Assert(tsLessEqual(9, 6, 9, 8), IsTrue)
}

func (s *testClientSuite) TestUpdateURLs(c *C) {
	members := []*pdpb.Member{
		{Name: "pd4", ClientUrls: []string{"tmp//pd4"}},
		{Name: "pd1", ClientUrls: []string{"tmp//pd1"}},
		{Name: "pd3", ClientUrls: []string{"tmp//pd3"}},
		{Name: "pd2", ClientUrls: []string{"tmp//pd2"}},
	}
	getURLs := func(ms []*pdpb.Member) (urls []string) {
		for _, m := range ms {
			urls = append(urls, m.GetClientUrls()[0])
		}
		return
	}
	cli := &baseClient{}
	cli.updateURLs(members[1:])
	c.Assert(cli.urls, DeepEquals, getURLs([]*pdpb.Member{members[1], members[3], members[2]}))
	cli.updateURLs(members[1:])
	c.Assert(cli.urls, DeepEquals, getURLs([]*pdpb.Member{members[1], members[3], members[2]}))
	cli.updateURLs(members)
	c.Assert(cli.urls, DeepEquals, getURLs([]*pdpb.Member{members[1], members[3], members[2], members[0]}))
}

var _ = Suite(&testClientCtxSuite{})

type testClientCtxSuite struct{}

func (s *testClientCtxSuite) TestClientCtx(c *C) {
	start := time.Now()
	ctx, cancel := context.WithTimeout(context.TODO(), time.Second*3)
	defer cancel()
	_, err := NewClientWithContext(ctx, []string{"127.0.0.1:8080"}, SecurityOption{})
	c.Assert(err, NotNil)
	c.Assert(time.Since(start), Less, time.Second*4)
}

func (s *testClientCtxSuite) TestClientWithRetry(c *C) {
	start := time.Now()
	_, err := NewClientWithContext(context.TODO(), []string{"127.0.0.1:8080"}, SecurityOption{}, WithMaxErrorRetry(5))
	c.Assert(err, NotNil)
	c.Assert(time.Since(start), Less, time.Second*6)
}

var _ = Suite(&testClientDialOptionSuite{})

type testClientDialOptionSuite struct{}

func (s *testClientDialOptionSuite) TestGRPCDialOption(c *C) {
	start := time.Now()
	ctx, cancel := context.WithTimeout(context.TODO(), 500*time.Millisecond)
	defer cancel()
	// nolint
	cli := &baseClient{
		urls:                 []string{"http://127.0.0.1:8080"},
		checkLeaderCh:        make(chan struct{}, 1),
		checkTSODispatcherCh: make(chan struct{}, 1),
		ctx:                  ctx,
		cancel:               cancel,
		security:             SecurityOption{},
		gRPCDialOptions:      []grpc.DialOption{grpc.WithBlock()},
	}

	err := cli.updateMember()
	c.Assert(err, NotNil)
	c.Assert(time.Since(start), Greater, 500*time.Millisecond)
}

var _ = Suite(&testTsoRequestSuite{})

type testTsoRequestSuite struct{}

func (s *testTsoRequestSuite) TestTsoRequestWait(c *C) {
	ctx, cancel := context.WithCancel(context.Background())
	req := &tsoRequest{
		done:       make(chan error, 1),
		physical:   0,
		logical:    0,
		requestCtx: context.TODO(),
		clientCtx:  ctx,
	}
	cancel()
	_, _, err := req.Wait()
	c.Assert(errors.Cause(err), Equals, context.Canceled)

	ctx, cancel = context.WithCancel(context.Background())
	req = &tsoRequest{
		done:       make(chan error, 1),
		physical:   0,
		logical:    0,
		requestCtx: ctx,
		clientCtx:  context.TODO(),
	}
	cancel()
	_, _, err = req.Wait()
	c.Assert(errors.Cause(err), Equals, context.Canceled)
}
<|endoftext|>