<commit_before>package server

import (
	"fmt"
	"github.com/Aptomi/aptomi/pkg/engine"
	"github.com/Aptomi/aptomi/pkg/engine/apply"
	"github.com/Aptomi/aptomi/pkg/engine/diff"
	"github.com/Aptomi/aptomi/pkg/engine/resolve"
	"github.com/Aptomi/aptomi/pkg/event"
	"github.com/Aptomi/aptomi/pkg/plugin"
	"github.com/Aptomi/aptomi/pkg/plugin/helm"
	"github.com/Aptomi/aptomi/pkg/runtime"
	log "github.com/Sirupsen/logrus"
	"time"
)

func logError(err interface{}) {
	log.Errorf("Error while enforcing policy: %s", err)
}

func (server *Server) enforceLoop() error {
	for {
		err := server.enforce()
		if err != nil {
			logError(err)
		}
		time.Sleep(server.cfg.Enforcer.Interval)
	}
}

func (server *Server) enforce() error {
	server.enforcementIdx++

	defer func() {
		if err := recover(); err != nil {
			logError(err)
		}
	}()

	// todo think about initial state when there is no revision at all
	currRevision, err := server.store.GetRevision(runtime.LastGen)
	if err != nil {
		return fmt.Errorf("unable to get curr revision: %s", err)
	}

	// Mark last Revision as failed if it wasn't completed
	if currRevision != nil && currRevision.Status == engine.RevisionStatusInProgress {
		currRevision.Status = engine.RevisionStatusError
		revErr := server.store.UpdateRevision(currRevision)
		if revErr != nil {
			log.Warnf("(enforce-%d) Error while setting current revision that is in progress to error state: %s", server.enforcementIdx, revErr)
		}
		log.Infof("(enforce-%d) Current revision that is in progress was reset to error state", server.enforcementIdx)
	}

	desiredPolicy, desiredPolicyGen, err := server.store.GetPolicy(runtime.LastGen)
	if err != nil {
		return fmt.Errorf("error while getting desiredPolicy: %s", err)
	}

	// if policy is not found, it means it somehow was not initialized correctly. let's return error
	if desiredPolicy == nil {
		return fmt.Errorf("desiredPolicy is nil, does not exist in the store")
	}

	actualState, err := server.store.GetActualState()
	if err != nil {
		return fmt.Errorf("error while getting actual state: %s", err)
	}

	eventLog := event.NewLog(fmt.Sprintf("enforce-%d-resolve", server.enforcementIdx), true)
	resolver := resolve.NewPolicyResolver(desiredPolicy, server.externalData, eventLog)
	desiredState, err := resolver.ResolveAllDependencies()
	if err != nil {
		// todo save eventlog

		if currRevision == nil || currRevision.Policy != desiredPolicyGen || currRevision.Status != engine.RevisionStatusError {
			rev, revErr := server.store.NewRevision(desiredPolicyGen)
			if revErr != nil {
				log.Warnf("(enforce-%d) Error while creating revision to record resolution error: %s", server.enforcementIdx, revErr)
			}

			rev.Status = engine.RevisionStatusError
			revErr = server.store.SaveRevision(rev)
			if revErr != nil {
				log.Warnf("(enforce-%d) Error while saving revision to record resolution error: %s", server.enforcementIdx, revErr)
			}
		}

		return fmt.Errorf("cannot resolve desiredPolicy: %s", err)
	}

	stateDiff := diff.NewPolicyResolutionDiff(desiredState, actualState)

	nextRevision, err := server.store.NewRevision(desiredPolicyGen)
	if err != nil {
		return fmt.Errorf("unable to get next revision: %s", err)
	}

	// policy changed while no actions needed to achieve desired state
	if len(stateDiff.Actions) <= 0 && currRevision != nil && currRevision.Policy == nextRevision.Policy {
		log.Infof("(enforce-%d) No changes, policy gen %d", server.enforcementIdx, desiredPolicyGen)
		return nil
	}
	log.Infof("(enforce-%d) New revision %d, policy gen %d, %d actions need to be applied", server.enforcementIdx, nextRevision.GetGeneration(), desiredPolicyGen, len(stateDiff.Actions))

	// todo save eventlog (if there were changes?)

	// todo if policy gen changed, we still need to save revision but with progress == done

	// Save revision
	err = server.store.SaveRevision(nextRevision)
	if err != nil {
		return fmt.Errorf("error while saving new revision: %s", err)
	}

	// Build plugin registry
	var pluginRegistry plugin.Registry
	if server.cfg.Enforcer.Noop {
		log.Infof("(enforce-%d) Applying changes in noop mode (sleep per action = %d seconds)", server.enforcementIdx, server.cfg.Enforcer.NoopSleep)
		pluginRegistry = &plugin.MockRegistry{
			DeployPlugin:      &plugin.MockDeployPlugin{SleepTime: time.Second * time.Duration(server.cfg.Enforcer.NoopSleep)},
			PostProcessPlugin: &plugin.MockPostProcessPlugin{},
		}
	} else {
		log.Infof("(enforce-%d) Applying changes", server.enforcementIdx)
		helmIstio := helm.NewPlugin(server.cfg.Helm)
		pluginRegistry = plugin.NewRegistry(
			[]plugin.DeployPlugin{helmIstio},
			[]plugin.PostProcessPlugin{helmIstio},
		)
	}

	eventLog = event.NewLog(fmt.Sprintf("enforce-%d-apply", server.enforcementIdx), true)
	applier := apply.NewEngineApply(desiredPolicy, desiredState, actualState, server.store.GetActualStateUpdater(), server.externalData, pluginRegistry, stateDiff.Actions, eventLog, server.store.GetRevisionProgressUpdater(nextRevision))
	_, err = applier.Apply()

	// todo save eventlog

	if err != nil {
		return fmt.Errorf("error while applying new revision: %s", err)
	}
	log.Infof("(enforce-%d) New revision %d successfully applied, %d component instances", server.enforcementIdx, nextRevision.GetGeneration(), len(desiredState.GetComponentProcessingOrder()))

	return nil
}
<commit_msg>Fix linter<commit_after>package server

import (
	"fmt"
	"github.com/Aptomi/aptomi/pkg/engine"
	"github.com/Aptomi/aptomi/pkg/engine/apply"
	"github.com/Aptomi/aptomi/pkg/engine/diff"
	"github.com/Aptomi/aptomi/pkg/engine/resolve"
	"github.com/Aptomi/aptomi/pkg/event"
	"github.com/Aptomi/aptomi/pkg/plugin"
	"github.com/Aptomi/aptomi/pkg/plugin/helm"
	"github.com/Aptomi/aptomi/pkg/runtime"
	log "github.com/Sirupsen/logrus"
	"time"
)

func logError(err interface{}) {
	log.Errorf("Error while enforcing policy: %s", err)
}

func (server *Server) enforceLoop() error {
	for {
		err := server.enforce()
		if err != nil {
			logError(err)
		}
		time.Sleep(server.cfg.Enforcer.Interval)
	}
}

func (server *Server) enforce() error {
	server.enforcementIdx++

	defer func() {
		if err := recover(); err != nil {
			logError(err)
		}
	}()

	// todo think about initial state when there is no revision at all
	currRevision, err := server.store.GetRevision(runtime.LastGen)
	if err != nil {
		return fmt.Errorf("unable to get curr revision: %s", err)
	}

	// Mark last Revision as failed if it wasn't completed
	if currRevision != nil && currRevision.Status == engine.RevisionStatusInProgress {
		currRevision.Status = engine.RevisionStatusError
		revErr := server.store.UpdateRevision(currRevision)
		if revErr != nil {
			log.Warnf("(enforce-%d) Error while setting current revision that is in progress to error state: %s", server.enforcementIdx, revErr)
		}
		log.Infof("(enforce-%d) Current revision that is in progress was reset to error state", server.enforcementIdx)
	}

	desiredPolicy, desiredPolicyGen, err := server.store.GetPolicy(runtime.LastGen)
	if err != nil {
		return fmt.Errorf("error while getting desiredPolicy: %s", err)
	}

	// if policy is not found, it means it somehow was not initialized correctly. let's return error
	if desiredPolicy == nil {
		return fmt.Errorf("desiredPolicy is nil, does not exist in the store")
	}

	actualState, err := server.store.GetActualState()
	if err != nil {
		return fmt.Errorf("error while getting actual state: %s", err)
	}

	eventLog := event.NewLog(fmt.Sprintf("enforce-%d-resolve", server.enforcementIdx), true)
	resolver := resolve.NewPolicyResolver(desiredPolicy, server.externalData, eventLog)
	desiredState, err := resolver.ResolveAllDependencies()
	if err != nil {
		// todo save eventlog
		server.saveErrRevision(currRevision, desiredPolicyGen)

		return fmt.Errorf("cannot resolve desiredPolicy: %s", err)
	}

	stateDiff := diff.NewPolicyResolutionDiff(desiredState, actualState)

	nextRevision, err := server.store.NewRevision(desiredPolicyGen)
	if err != nil {
		return fmt.Errorf("unable to get next revision: %s", err)
	}

	// policy changed while no actions needed to achieve desired state
	if len(stateDiff.Actions) <= 0 && currRevision != nil && currRevision.Policy == nextRevision.Policy {
		log.Infof("(enforce-%d) No changes, policy gen %d", server.enforcementIdx, desiredPolicyGen)
		return nil
	}
	log.Infof("(enforce-%d) New revision %d, policy gen %d, %d actions need to be applied", server.enforcementIdx, nextRevision.GetGeneration(), desiredPolicyGen, len(stateDiff.Actions))

	// todo save eventlog (if there were changes?)

	// todo if policy gen changed, we still need to save revision but with progress == done

	// Save revision
	err = server.store.SaveRevision(nextRevision)
	if err != nil {
		return fmt.Errorf("error while saving new revision: %s", err)
	}

	// Build plugin registry
	var pluginRegistry plugin.Registry
	if server.cfg.Enforcer.Noop {
		log.Infof("(enforce-%d) Applying changes in noop mode (sleep per action = %d seconds)", server.enforcementIdx, server.cfg.Enforcer.NoopSleep)
		pluginRegistry = &plugin.MockRegistry{
			DeployPlugin:      &plugin.MockDeployPlugin{SleepTime: time.Second * time.Duration(server.cfg.Enforcer.NoopSleep)},
			PostProcessPlugin: &plugin.MockPostProcessPlugin{},
		}
	} else {
		log.Infof("(enforce-%d) Applying changes", server.enforcementIdx)
		helmIstio := helm.NewPlugin(server.cfg.Helm)
		pluginRegistry = plugin.NewRegistry(
			[]plugin.DeployPlugin{helmIstio},
			[]plugin.PostProcessPlugin{helmIstio},
		)
	}

	eventLog = event.NewLog(fmt.Sprintf("enforce-%d-apply", server.enforcementIdx), true)
	applier := apply.NewEngineApply(desiredPolicy, desiredState, actualState, server.store.GetActualStateUpdater(), server.externalData, pluginRegistry, stateDiff.Actions, eventLog, server.store.GetRevisionProgressUpdater(nextRevision))
	_, err = applier.Apply()

	// todo save eventlog

	if err != nil {
		return fmt.Errorf("error while applying new revision: %s", err)
	}
	log.Infof("(enforce-%d) New revision %d successfully applied, %d component instances", server.enforcementIdx, nextRevision.GetGeneration(), len(desiredState.GetComponentProcessingOrder()))

	return nil
}

func (server *Server) saveErrRevision(currRevision *engine.Revision, desiredPolicyGen runtime.Generation) {
	if currRevision == nil || currRevision.Policy != desiredPolicyGen || currRevision.Status != engine.RevisionStatusError {
		rev, revErr := server.store.NewRevision(desiredPolicyGen)
		if revErr != nil {
			log.Warnf("(enforce-%d) Error while creating revision to record resolution error: %s", server.enforcementIdx, revErr)
		}

		rev.Status = engine.RevisionStatusError
		revErr = server.store.SaveRevision(rev)
		if revErr != nil {
			log.Warnf("(enforce-%d) Error while saving revision to record resolution error: %s", server.enforcementIdx, revErr)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package system

// Operator defines reload, maintenance and shutdown interface
type Operator interface {
	Reload() error
	Maintenance() error
	Shutdown() error
}

// Handling implements simplest Operator interface
type Handling struct{}

// Reload implementation
func (h Handling) Reload() error {
	return nil
}

// Maintenance implementation
func (h Handling) Maintenance() error {
	return nil
}

// Shutdown implementation
func (h Handling) Shutdown() error {
	return nil
}
<commit_msg>Sows error for methods that isn't implemented<commit_after>// Copyright 2017 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package system

import "errors"

// ErrNotImplemented declares error for method that isn't implemented
var ErrNotImplemented = errors.New("This method is not implemented")

// Operator defines reload, maintenance and shutdown interface
type Operator interface {
	Reload() error
	Maintenance() error
	Shutdown() error
}

// Handling implements simplest Operator interface
type Handling struct{}

// Reload operation implementation
func (h Handling) Reload() error {
	return ErrNotImplemented
}

// Maintenance operation implementation
func (h Handling) Maintenance() error {
	return ErrNotImplemented
}

// Shutdown operation implementation
func (h Handling) Shutdown() error {
	return ErrNotImplemented
}
<|endoftext|>


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

//go:generate go get github.com/cznic/golex
//go:generate golex -o=lex.l.go lex.l

// Package textparse contains an efficient parser for the Prometheus text format.
package textparse

import (
	"errors"
	"fmt"
	"io"
	"math"
	"sort"
	"strconv"
	"strings"
	"unicode/utf8"
	"unsafe"

	"github.com/prometheus/prometheus/pkg/labels"
	"github.com/prometheus/prometheus/pkg/value"
)

type lexer struct {
	b     []byte
	i     int
	start int
	err   error
	state int
}

type token int

const (
	tInvalid   token = -1
	tEOF       token = 0
	tLinebreak token = iota
	tWhitespace
	tHelp
	tType
	tText
	tComment
	tBlank
	tMName
	tBraceOpen
	tBraceClose
	tLName
	tLValue
	tComma
	tEqual
	tTimestamp
	tValue
)

func (t token) String() string {
	switch t {
	case tInvalid:
		return "INVALID"
	case tEOF:
		return "EOF"
	case tLinebreak:
		return "LINEBREAK"
	case tWhitespace:
		return "WHITESPACE"
	case tHelp:
		return "HELP"
	case tType:
		return "TYPE"
	case tText:
		return "TEXT"
	case tComment:
		return "COMMENT"
	case tBlank:
		return "BLANK"
	case tMName:
		return "MNAME"
	case tBraceOpen:
		return "BOPEN"
	case tBraceClose:
		return "BCLOSE"
	case tLName:
		return "LNAME"
	case tLValue:
		return "LVALUE"
	case tEqual:
		return "EQUAL"
	case tComma:
		return "COMMA"
	case tTimestamp:
		return "TIMESTAMP"
	case tValue:
		return "VALUE"
	}
	return fmt.Sprintf("<invalid: %d>", t)
}

// buf returns the buffer of the current token.
func (l *lexer) buf() []byte {
	return l.b[l.start:l.i]
}

func (l *lexer) cur() byte {
	return l.b[l.i]
}

// next advances the lexer to the next character.
func (l *lexer) next() byte {
	l.i++
	if l.i >= len(l.b) {
		l.err = io.EOF
		return byte(tEOF)
	}
	// Lex struggles with null bytes. If we are in a label value or help string, where
	// they are allowed, consume them here immediately.
	for l.b[l.i] == 0 && (l.state == sLValue || l.state == sMeta2 || l.state == sComment) {
		l.i++
	}
	return l.b[l.i]
}

func (l *lexer) Error(es string) {
	l.err = errors.New(es)
}

// Parser parses samples from a byte slice of samples in the official
// Prometheus text exposition format.
type Parser struct {
	l       *lexer
	series  []byte
	text    []byte
	mtype   MetricType
	val     float64
	ts      int64
	hasTS   bool
	start   int
	offsets []int
}

// New returns a new parser of the byte slice.
func New(b []byte) *Parser {
	return &Parser{l: &lexer{b: append(b, '\n')}}
}

// Series returns the bytes of the series, the timestamp if set, and the value
// of the current sample.
func (p *Parser) Series() ([]byte, *int64, float64) {
	if p.hasTS {
		return p.series, &p.ts, p.val
	}
	return p.series, nil, p.val
}

// Help returns the metric name and help text in the current entry.
// Must only be called after Next returned a help entry.
// The returned byte slices become invalid after the next call to Next.
func (p *Parser) Help() ([]byte, []byte) {
	return p.l.b[p.offsets[0]:p.offsets[1]], p.text
}

// Type returns the metric name and type in the current entry.
// Must only be called after Next returned a type entry.
// The returned byte slices become invalid after the next call to Next.
func (p *Parser) Type() ([]byte, MetricType) {
	return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype
}

// Comment returns the text of the current comment.
// Must only be called after Next returned a comment entry.
// The returned byte slice becomes invalid after the next call to Next.
func (p *Parser) Comment() []byte {
	return p.text
}

// Metric writes the labels of the current sample into the passed labels.
// It returns the string from which the metric was parsed.
func (p *Parser) Metric(l *labels.Labels) string {
	// Allocate the full immutable string immediately, so we just
	// have to create references on it below.
	s := string(p.series)

	*l = append(*l, labels.Label{
		Name:  labels.MetricName,
		Value: s[:p.offsets[0]-p.start],
	})

	for i := 1; i < len(p.offsets); i += 4 {
		a := p.offsets[i] - p.start
		b := p.offsets[i+1] - p.start
		c := p.offsets[i+2] - p.start
		d := p.offsets[i+3] - p.start

		// Replacer causes allocations. Replace only when necessary.
		if strings.IndexByte(s[c:d], byte('\\')) >= 0 {
			*l = append(*l, labels.Label{Name: s[a:b], Value: replacer.Replace(s[c:d])})
			continue
		}
		*l = append(*l, labels.Label{Name: s[a:b], Value: s[c:d]})
	}

	// Sort labels. We can skip the first entry since the metric name is
	// already at the right place.
	sort.Sort((*l)[1:])

	return s
}

// nextToken returns the next token from the lexer. It skips over tabs
// and spaces.
func (p *Parser) nextToken() token {
	for {
		if tok := p.l.Lex(); tok != tWhitespace {
			return tok
		}
	}
}

// Entry represents the type of a parsed entry.
type Entry int

const (
	EntryInvalid Entry = -1
	EntryType    Entry = 0
	EntryHelp    Entry = 1
	EntrySeries  Entry = 2
	EntryComment Entry = 3
)

// MetricType represents metric type values.
type MetricType string

const (
	MetricTypeCounter   = "counter"
	MetricTypeGauge     = "gauge"
	MetricTypeHistogram = "histogram"
	MetricTypeSummary   = "summary"
	MetricTypeUntyped   = "untyped"
)

func parseError(exp string, got token) error {
	return fmt.Errorf("%s, got %q", exp, got)
}

// Next advances the parser to the next sample. It returns false if no
// more samples were read or an error occurred.
func (p *Parser) Next() (Entry, error) {
	var err error

	p.start = p.l.i
	p.offsets = p.offsets[:0]

	switch t := p.nextToken(); t {
	case tEOF:
		return EntryInvalid, io.EOF
	case tLinebreak:
		// Allow full blank lines.
		return p.Next()

	case tHelp, tType:
		switch t := p.nextToken(); t {
		case tMName:
			p.offsets = append(p.offsets, p.l.start, p.l.i)
		default:
			return EntryInvalid, parseError("expected metric name after HELP", t)
		}
		switch t := p.nextToken(); t {
		case tText:
			p.text = p.l.buf()[1:]
		default:
			return EntryInvalid, parseError("expected text in HELP", t)
		}
		switch t {
		case tType:
			switch s := yoloString(p.text); s {
			case "counter":
				p.mtype = MetricTypeCounter
			case "gauge":
				p.mtype = MetricTypeGauge
			case "histogram":
				p.mtype = MetricTypeHistogram
			case "summary":
				p.mtype = MetricTypeSummary
			case "untyped":
				p.mtype = MetricTypeUntyped
			default:
				return EntryInvalid, fmt.Errorf("invalid metric type %q", s)
			}
		case tHelp:
			if !utf8.Valid(p.text) {
				return EntryInvalid, fmt.Errorf("help text is not a valid utf8 string")
			}
		}
		if t := p.nextToken(); t != tLinebreak {
			return EntryInvalid, parseError("linebreak expected after metadata", t)
		}
		switch t {
		case tHelp:
			return EntryHelp, nil
		case tType:
			return EntryType, nil
		}
	case tComment:
		p.text = p.l.buf()
		if t := p.nextToken(); t != tLinebreak {
			return EntryInvalid, parseError("linebreak expected after comment", t)
		}
		return EntryComment, nil

	case tMName:
		p.offsets = append(p.offsets, p.l.i)
		p.series = p.l.b[p.start:p.l.i]

		t2 := p.nextToken()
		if t2 == tBraceOpen {
			if err := p.parseLVals(); err != nil {
				return EntryInvalid, err
			}
			p.series = p.l.b[p.start:p.l.i]
			t2 = p.nextToken()
		}
		if t2 != tValue {
			return EntryInvalid, parseError("expected value after metric", t)
		}
		if p.val, err = strconv.ParseFloat(yoloString(p.l.buf()), 64); err != nil {
			return EntryInvalid, err
		}
		// Ensure canonical NaN value.
		if math.IsNaN(p.val) {
			p.val = math.Float64frombits(value.NormalNaN)
		}
		p.hasTS = false
		switch p.nextToken() {
		case tLinebreak:
			break
		case tTimestamp:
			p.hasTS = true
			if p.ts, err = strconv.ParseInt(yoloString(p.l.buf()), 10, 64); err != nil {
				return EntryInvalid, err
			}
			if t2 := p.nextToken(); t2 != tLinebreak {
				return EntryInvalid, parseError("expected next entry after timestamp", t)
			}
		default:
			return EntryInvalid, parseError("expected timestamp or new record", t)
		}
		return EntrySeries, nil

	default:
		err = fmt.Errorf("%q is not a valid start token", t)
	}
	return EntryInvalid, err
}

func (p *Parser) parseLVals() error {
	t := p.nextToken()
	for {
		switch t {
		case tBraceClose:
			return nil
		case tLName:
		default:
			return parseError("expected label name", t)
		}
		p.offsets = append(p.offsets, p.l.start, p.l.i)

		if t := p.nextToken(); t != tEqual {
			return parseError("expected equal", t)
		}
		if t := p.nextToken(); t != tLValue {
			return parseError("expected label value", t)
		}
		if !utf8.Valid(p.l.buf()) {
			return fmt.Errorf("invalid UTF-8 label value")
		}

		// The lexer ensures the value string is quoted. Strip first
		// and last character.
		p.offsets = append(p.offsets, p.l.start+1, p.l.i-1)

		// Free trailing commas are allowed.
		if t = p.nextToken(); t == tComma {
			t = p.nextToken()
		}
	}
}

var replacer = strings.NewReplacer(
	`\"`, `"`,
	`\\`, `\`,
	`\n`, `
`,
	`\t`, `	`,
)

func yoloString(b []byte) string {
	return *((*string)(unsafe.Pointer(&b)))
}
<commit_msg>pkg/textparse: unescape help string<commit_after>// Copyright 2017 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:generate go get github.com/cznic/golex
//go:generate golex -o=lex.l.go lex.l

// Package textparse contains an efficient parser for the Prometheus text format.
package textparse

import (
	"errors"
	"fmt"
	"io"
	"math"
	"sort"
	"strconv"
	"strings"
	"unicode/utf8"
	"unsafe"

	"github.com/prometheus/prometheus/pkg/labels"
	"github.com/prometheus/prometheus/pkg/value"
)

type lexer struct {
	b     []byte
	i     int
	start int
	err   error
	state int
}

type token int

const (
	tInvalid   token = -1
	tEOF       token = 0
	tLinebreak token = iota
	tWhitespace
	tHelp
	tType
	tText
	tComment
	tBlank
	tMName
	tBraceOpen
	tBraceClose
	tLName
	tLValue
	tComma
	tEqual
	tTimestamp
	tValue
)

func (t token) String() string {
	switch t {
	case tInvalid:
		return "INVALID"
	case tEOF:
		return "EOF"
	case tLinebreak:
		return "LINEBREAK"
	case tWhitespace:
		return "WHITESPACE"
	case tHelp:
		return "HELP"
	case tType:
		return "TYPE"
	case tText:
		return "TEXT"
	case tComment:
		return "COMMENT"
	case tBlank:
		return "BLANK"
	case tMName:
		return "MNAME"
	case tBraceOpen:
		return "BOPEN"
	case tBraceClose:
		return "BCLOSE"
	case tLName:
		return "LNAME"
	case tLValue:
		return "LVALUE"
	case tEqual:
		return "EQUAL"
	case tComma:
		return "COMMA"
	case tTimestamp:
		return "TIMESTAMP"
	case tValue:
		return "VALUE"
	}
	return fmt.Sprintf("<invalid: %d>", t)
}

// buf returns the buffer of the current token.
func (l *lexer) buf() []byte {
	return l.b[l.start:l.i]
}

func (l *lexer) cur() byte {
	return l.b[l.i]
}

// next advances the lexer to the next character.
func (l *lexer) next() byte {
	l.i++
	if l.i >= len(l.b) {
		l.err = io.EOF
		return byte(tEOF)
	}
	// Lex struggles with null bytes. If we are in a label value or help string, where
	// they are allowed, consume them here immediately.
	for l.b[l.i] == 0 && (l.state == sLValue || l.state == sMeta2 || l.state == sComment) {
		l.i++
	}
	return l.b[l.i]
}

func (l *lexer) Error(es string) {
	l.err = errors.New(es)
}

// Parser parses samples from a byte slice of samples in the official
// Prometheus text exposition format.
type Parser struct {
	l       *lexer
	series  []byte
	text    []byte
	mtype   MetricType
	val     float64
	ts      int64
	hasTS   bool
	start   int
	offsets []int
}

// New returns a new parser of the byte slice.
func New(b []byte) *Parser {
	return &Parser{l: &lexer{b: append(b, '\n')}}
}

// Series returns the bytes of the series, the timestamp if set, and the value
// of the current sample.
func (p *Parser) Series() ([]byte, *int64, float64) {
	if p.hasTS {
		return p.series, &p.ts, p.val
	}
	return p.series, nil, p.val
}

// Help returns the metric name and help text in the current entry.
// Must only be called after Next returned a help entry.
// The returned byte slices become invalid after the next call to Next.
func (p *Parser) Help() ([]byte, []byte) {
	m := p.l.b[p.offsets[0]:p.offsets[1]]

	// Replacer causes allocations. Replace only when necessary.
	if strings.IndexByte(yoloString(p.text), byte('\\')) >= 0 {
		return m, []byte(helpReplacer.Replace(string(p.text)))
	}
	return m, p.text
}

// Type returns the metric name and type in the current entry.
// Must only be called after Next returned a type entry.
// The returned byte slices become invalid after the next call to Next.
func (p *Parser) Type() ([]byte, MetricType) {
	return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype
}

// Comment returns the text of the current comment.
// Must only be called after Next returned a comment entry.
// The returned byte slice becomes invalid after the next call to Next.
func (p *Parser) Comment() []byte {
	return p.text
}

// Metric writes the labels of the current sample into the passed labels.
// It returns the string from which the metric was parsed.
func (p *Parser) Metric(l *labels.Labels) string {
	// Allocate the full immutable string immediately, so we just
	// have to create references on it below.
	s := string(p.series)

	*l = append(*l, labels.Label{
		Name:  labels.MetricName,
		Value: s[:p.offsets[0]-p.start],
	})

	for i := 1; i < len(p.offsets); i += 4 {
		a := p.offsets[i] - p.start
		b := p.offsets[i+1] - p.start
		c := p.offsets[i+2] - p.start
		d := p.offsets[i+3] - p.start

		// Replacer causes allocations. Replace only when necessary.
		if strings.IndexByte(s[c:d], byte('\\')) >= 0 {
			*l = append(*l, labels.Label{Name: s[a:b], Value: lvalReplacer.Replace(s[c:d])})
			continue
		}
		*l = append(*l, labels.Label{Name: s[a:b], Value: s[c:d]})
	}

	// Sort labels. We can skip the first entry since the metric name is
	// already at the right place.
	sort.Sort((*l)[1:])

	return s
}

// nextToken returns the next token from the lexer. It skips over tabs
// and spaces.
func (p *Parser) nextToken() token {
	for {
		if tok := p.l.Lex(); tok != tWhitespace {
			return tok
		}
	}
}

// Entry represents the type of a parsed entry.
type Entry int

const (
	EntryInvalid Entry = -1
	EntryType    Entry = 0
	EntryHelp    Entry = 1
	EntrySeries  Entry = 2
	EntryComment Entry = 3
)

// MetricType represents metric type values.
type MetricType string

const (
	MetricTypeCounter   = "counter"
	MetricTypeGauge     = "gauge"
	MetricTypeHistogram = "histogram"
	MetricTypeSummary   = "summary"
	MetricTypeUntyped   = "untyped"
)

func parseError(exp string, got token) error {
	return fmt.Errorf("%s, got %q", exp, got)
}

// Next advances the parser to the next sample. It returns false if no
// more samples were read or an error occurred.
func (p *Parser) Next() (Entry, error) {
	var err error

	p.start = p.l.i
	p.offsets = p.offsets[:0]

	switch t := p.nextToken(); t {
	case tEOF:
		return EntryInvalid, io.EOF
	case tLinebreak:
		// Allow full blank lines.
		return p.Next()

	case tHelp, tType:
		switch t := p.nextToken(); t {
		case tMName:
			p.offsets = append(p.offsets, p.l.start, p.l.i)
		default:
			return EntryInvalid, parseError("expected metric name after HELP", t)
		}
		switch t := p.nextToken(); t {
		case tText:
			p.text = p.l.buf()[1:]
		default:
			return EntryInvalid, parseError("expected text in HELP", t)
		}
		switch t {
		case tType:
			switch s := yoloString(p.text); s {
			case "counter":
				p.mtype = MetricTypeCounter
			case "gauge":
				p.mtype = MetricTypeGauge
			case "histogram":
				p.mtype = MetricTypeHistogram
			case "summary":
				p.mtype = MetricTypeSummary
			case "untyped":
				p.mtype = MetricTypeUntyped
			default:
				return EntryInvalid, fmt.Errorf("invalid metric type %q", s)
			}
		case tHelp:
			if !utf8.Valid(p.text) {
				return EntryInvalid, fmt.Errorf("help text is not a valid utf8 string")
			}
		}
		if t := p.nextToken(); t != tLinebreak {
			return EntryInvalid, parseError("linebreak expected after metadata", t)
		}
		switch t {
		case tHelp:
			return EntryHelp, nil
		case tType:
			return EntryType, nil
		}
	case tComment:
		p.text = p.l.buf()
		if t := p.nextToken(); t != tLinebreak {
			return EntryInvalid, parseError("linebreak expected after comment", t)
		}
		return EntryComment, nil

	case tMName:
		p.offsets = append(p.offsets, p.l.i)
		p.series = p.l.b[p.start:p.l.i]

		t2 := p.nextToken()
		if t2 == tBraceOpen {
			if err := p.parseLVals(); err != nil {
				return EntryInvalid, err
			}
			p.series = p.l.b[p.start:p.l.i]
			t2 = p.nextToken()
		}
		if t2 != tValue {
			return EntryInvalid, parseError("expected value after metric", t)
		}
		if p.val, err = strconv.ParseFloat(yoloString(p.l.buf()), 64); err != nil {
			return EntryInvalid, err
		}
		// Ensure canonical NaN value.
		if math.IsNaN(p.val) {
			p.val = math.Float64frombits(value.NormalNaN)
		}
		p.hasTS = false
		switch p.nextToken() {
		case tLinebreak:
			break
		case tTimestamp:
			p.hasTS = true
			if p.ts, err = strconv.ParseInt(yoloString(p.l.buf()), 10, 64); err != nil {
				return EntryInvalid, err
			}
			if t2 := p.nextToken(); t2 != tLinebreak {
				return EntryInvalid, parseError("expected next entry after timestamp", t)
			}
		default:
			return EntryInvalid, parseError("expected timestamp or new record", t)
		}
		return EntrySeries, nil

	default:
		err = fmt.Errorf("%q is not a valid start token", t)
	}
	return EntryInvalid, err
}

func (p *Parser) parseLVals() error {
	t := p.nextToken()
	for {
		switch t {
		case tBraceClose:
			return nil
		case tLName:
		default:
			return parseError("expected label name", t)
		}
		p.offsets = append(p.offsets, p.l.start, p.l.i)

		if t := p.nextToken(); t != tEqual {
			return parseError("expected equal", t)
		}
		if t := p.nextToken(); t != tLValue {
			return parseError("expected label value", t)
		}
		if !utf8.Valid(p.l.buf()) {
			return fmt.Errorf("invalid UTF-8 label value")
		}

		// The lexer ensures the value string is quoted. Strip first
		// and last character.
		p.offsets = append(p.offsets, p.l.start+1, p.l.i-1)

		// Free trailing commas are allowed.
		if t = p.nextToken(); t == tComma {
			t = p.nextToken()
		}
	}
}

var lvalReplacer = strings.NewReplacer(
	`\"`, "\"",
	`\\`, "\\",
	`\n`, "\n",
)

var helpReplacer = strings.NewReplacer(
	`\\`, "\\",
	`\n`, "\n",
)

func yoloString(b []byte) string {
	return *((*string)(unsafe.Pointer(&b)))
}
<|endoftext|>


<commit_before>package utils

import (
	"os"

	"github.com/spf13/cobra"
)

// AppConfig provides the global configuration of the application
type AppConfig struct {
	HTTPListenAddress string
	GRPCListenAddress string
}

// NewAppConfig sets up all the basic configuration data from flags, env, etc
func NewAppConfig(cmd *cobra.Command) (*AppConfig, error) {

	grpcAddr, err := cmd.Flags().GetString("grpc")
	if err != nil {
	}

	httpAddr, err := cmd.Flags().GetString("http")
	if err != nil {
		return nil, err
	}

	grpc := os.Getenv("GRPC_ADDRESS")
	if len(grpc) == 0 {
		grpc = grpcAddr
	}

	addr := os.Getenv("HTTP_ADDRESS")
	if len(addr) == 0 {
		addr = httpAddr
	}

	return &AppConfig{HTTPListenAddress: addr, GRPCListenAddress: grpc}, nil
}
<commit_msg>playing with viper in appConfig.go<commit_after>package utils

import (
	"bytes"
	"encoding/json"
	"log"
	"os"
	"path"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// AppConfig provides the global configuration of the application.
type AppConfig struct {
	HTTPListenAddress string `json:"http"`
	GRPCListenAddress string `json:"grpc"`
	User              User   `json:"user"`
}

type User struct {
	UserID string `json:"userID"`
	Name   string `json:"name"`
}

type TestConfig struct {
	HTTPListenAddress string `json:"http"`
	User              User   `json:"user"`
}

var (
	defaultConfig = &AppConfig{
		HTTPListenAddress: ":8080",
		GRPCListenAddress: ":50051",
		User: User{
			UserID: "bones177",
			Name:   "Bob Jones",
		},
	}
)

// NewAppConfig sets up all the basic configuration data from flags, env, etc
func NewAppConfig(cmd *cobra.Command) (*AppConfig, error) {

	defaultSettings, err := json.Marshal(defaultConfig)
	if err != nil {
		panic(err)
	}
	log.Printf("defaultConfig    : %+v", defaultConfig)
	log.Printf("defaultSettings  : %s", defaultSettings)

	viper.SetConfigType("json")
	viper.ReadConfig(bytes.NewReader(defaultSettings))
	viper.SetEnvPrefix("fubar")
	log.Printf("user.name        : %s", viper.GetString("user.name"))
	log.Printf("FUBAR_GORF       : %s", viper.GetString("GORF"))
	log.Printf("gorf             : %s", viper.GetString("gorf"))

	viper.BindPFlags(cmd.Flags())
	log.Printf("httpaddress      : %s", viper.GetString("http"))

	log.Printf("GRPCListenAddress: %s", viper.GetString("GRPCListenAddress"))
	log.Printf("grpc             : %s", viper.GetString("grpc"))

	var activeConfig AppConfig
	err = viper.Unmarshal(&activeConfig)
	if err != nil {
		panic(err)
	}
	log.Printf("TestConfig.HTTPListenAddress: %s", activeConfig.HTTPListenAddress)
	log.Printf("TestConfig.GRPCListenAddress: %s", activeConfig.GRPCListenAddress)
	log.Printf("TestConfig.user.name        : %s", activeConfig.User.Name)
	log.Printf("TestConfig.user.userID      : %s", activeConfig.User.UserID)

	log.Printf("basename: %s", path.Base(os.Args[0]))

	grpcAddr, err := cmd.Flags().GetString("grpc")
	if err != nil {
	}

	httpAddr, err := cmd.Flags().GetString("http")
	if err != nil {
		return nil, err
	}

	grpc := os.Getenv("GRPC_ADDRESS")
	if len(grpc) == 0 {
		grpc = grpcAddr
	}

	addr := os.Getenv("HTTP_ADDRESS")
	if len(addr) == 0 {
		addr = httpAddr
	}

	return &AppConfig{HTTPListenAddress: addr, GRPCListenAddress: grpc}, nil
}
<|endoftext|>


<commit_before>package server

import (
	dnet "doozer/net"
	"doozer/paxos"
	"doozer/proto"
	"doozer/store"
	"doozer/util"
	"encoding/binary"
	"io"
	"net"
	"os"
	pb "goprotobuf.googlecode.com/hg/proto"
	"rand"
	"strconv"
	"sync"
	"time"
)

const packetSize = 3000

const (
	sessionLease = 60e9 // ns == 60s
	sessionPad   = 5e8 // ns == .5s
)

var (
	ErrPoisoned = os.NewError("poisoned")
)

var (
	other       = proto.NewResponse_Err(proto.Response_OTHER)
	redirect    = proto.NewResponse_Err(proto.Response_REDIRECT)
	newErrCode  = proto.NewResponse_Err
	tagInUse    = &R{ErrCode: newErrCode(proto.Response_TAG_IN_USE)}
	isDir       = &R{ErrCode: newErrCode(proto.Response_ISDIR)}
	badSnap     = &R{ErrCode: newErrCode(proto.Response_INVALID_SNAP)}
	readonly    = &R{
		ErrCode: newErrCode(proto.Response_OTHER),
		ErrDetail: pb.String("no known writeable addresses"),
	}
	badTag      = &R{
		ErrCode: newErrCode(proto.Response_OTHER),
		ErrDetail: pb.String("unknown tag"),
	}
)

func errResponse(e os.Error) *R {
	return &R{ErrCode: other, ErrDetail: pb.String(e.String())}
}

// Response flags
const (
	Valid = 1 << iota
	Done
)

var slots = store.MustCompileGlob("/doozer/slot/*")

type T proto.Request
type R proto.Response

type OpError struct {
	Detail string
}

type Manager interface {
	paxos.Proposer
	ProposeOnce(v string, c chan bool) store.Event
	PutFrom(string, paxos.Msg)
	Alpha() int
}

type Server struct {
	Conn net.PacketConn
	Addr string
	St   *store.Store
	Mg   Manager
	Self string
}

func (sv *Server) ServeUdp(outs chan paxos.Packet) {
	r := dnet.Ackify(sv.Conn, outs)

	for p := range r {
		sv.Mg.PutFrom(p.Addr, p.Msg)
	}
}

var clg = util.NewLogger("cal")

func (s *Server) Serve(l net.Listener, cal chan int) os.Error {
	for {
		rw, err := l.Accept()
		if err != nil {
			if e, ok := err.(*net.OpError); ok && e.Error == os.EINVAL {
				return nil
			}
			return err
		}
		c := &conn{
			c:       rw,
			s:       s,
			cal:     closed(cal),
			snaps:   make(map[int32]store.Getter),
			cancels: make(map[int32]chan bool),
		}
		go c.serve()
	}

	panic("unreachable")
}

func (sv *Server) cals() []string {
	cals := make([]string, 0)
	_, g := sv.St.Snap()
	store.Walk(g, slots, func(_, body, _ string) {
		if len(body) > 0 {
			cals = append(cals, body)
		}
	})
	return cals
}

// Repeatedly propose nop values until a successful read from `done`.
func (sv *Server) AdvanceUntil(done chan int) {
	for _, ok := <-done; !ok; _, ok = <-done {
		sv.Mg.Propose(store.Nop, nil)
	}
}

type conn struct {
	c        net.Conn
	s        *Server
	cal      bool
	sid      int32
	snaps    map[int32]store.Getter
	slk      sync.RWMutex
	cancels  map[int32]chan bool
	wl       sync.Mutex // write lock
	poisoned bool
}

func (c *conn) readBuf() (*T, os.Error) {
	var size int32
	err := binary.Read(c.c, binary.BigEndian, &size)
	if err != nil {
		return nil, err
	}

	buf := make([]byte, size)
	_, err = io.ReadFull(c.c, buf)
	if err != nil {
		return nil, err
	}

	var t T
	err = pb.Unmarshal(buf, &t)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func (c *conn) makeCancel(t *T) chan bool {
	tag := pb.GetInt32(t.Tag)

	c.wl.Lock()
	defer c.wl.Unlock()

	if _, ok := c.cancels[tag]; ok {
		return nil
	}

	ch := make(chan bool)
	c.cancels[tag] = ch
	return ch
}

func (c *conn) cancellable(t *T, f func(chan bool) *R) *R {
	ch := make(chan *R, 1)
	cancel := c.makeCancel(t)
	if cancel == nil {
		return tagInUse
	}

	go func() { ch <- f(cancel) }()

	go func() {
		r := <-ch
		if r != nil {
			c.respond(t, Valid|Done, r)
		}
	}()

	return nil
}

func (c *conn) respond(t *T, flag int32, r *R) os.Error {
	r.Tag = t.Tag
	r.Flags = pb.Int32(flag)
	tag := pb.GetInt32(t.Tag)

	c.wl.Lock()
	defer c.wl.Unlock()

	if c.poisoned {
		return ErrPoisoned
	}

	if ch := c.cancels[tag]; ch != nil && flag&Done != 0 {
		c.cancels[tag] = nil, false
		close(ch)
	}

	buf, err := pb.Marshal(r)
	if err != nil {
		c.poisoned = true
		return err
	}

	err = binary.Write(c.c, binary.BigEndian, int32(len(buf)))
	if err != nil {
		c.poisoned = true
		return err
	}

	for len(buf) > 0 {
		n, err := c.c.Write(buf)
		if err != nil {
			c.poisoned = true
			return err
		}

		buf = buf[n:]
	}

	return nil
}

func (c *conn) redirect() *R {
	cals := c.s.cals()
	if len(cals) < 1 {
		return readonly
	}

	cal := cals[rand.Intn(len(cals))]
	parts, cas := c.s.St.Get("/doozer/info/" + cal + "/public-addr")
	if cas == store.Dir && cas == store.Missing {
		return readonly
	}

	return &R{ErrCode: redirect, ErrDetail: &parts[0]}
}

func (c *conn) get(t *T) *R {
	var g store.Getter
	id := pb.GetInt32(t.Id)
	if id == 0 {
		g = c.s.St
	} else {
		var ok bool
		c.slk.RLock()
		g, ok = c.snaps[id]
		c.slk.RUnlock()
		if !ok {
			return badSnap
		}
	}

	v, cas := g.Get(pb.GetString(t.Path))
	if cas == store.Dir {
		return isDir
	}

	var r R
	r.Cas = &cas
	if len(v) == 1 { // not missing
		r.Value = []byte(v[0])
	}
	return &r
}

func (c *conn) set(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		_, cas, err := paxos.Set(c.s.Mg, *t.Path, string(t.Value), *t.Cas, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		return &R{Cas: &cas}
	})
}

func (c *conn) del(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		err := paxos.Del(c.s.Mg, *t.Path, *t.Cas, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		return &R{}
	})
}

func (c *conn) noop(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		ev := c.s.Mg.ProposeOnce(store.Nop, cancel)
		if ev.Err == paxos.ErrCancel {
			return nil
		}
		return &R{}
	})
}

func (c *conn) join(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		key := "/doozer/members/" + pb.GetString(t.Path)
		seqn, _, err := paxos.Set(c.s.Mg, key, string(t.Value), store.Missing, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		done := make(chan int)
		go c.s.AdvanceUntil(done)
		c.s.St.Sync(seqn + uint64(c.s.Mg.Alpha()))
		close(done)
		seqn, snap := c.s.St.Snapshot()
		seqn1 := int64(seqn)
		return &R{Seqn: &seqn1, Value: []byte(snap)}
	})
}

func (c *conn) checkin(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		body := strconv.Itoa64(time.Nanoseconds() + sessionLease)
		sess := pb.GetString(t.Path)
		cas := pb.GetString(t.Cas)
		_, cas, err := paxos.Set(c.s.Mg, "/session/"+sess, body, cas, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		select {
		case <-time.After(sessionLease - sessionPad):
		case <-cancel:
			return nil
		}
		return &R{Cas: &cas}
	})
}

func (c *conn) cancel(t *T) *R {
	tag := pb.GetInt32(t.Id)

	c.wl.Lock()
	ch := c.cancels[tag]
	c.wl.Unlock()

	if ch != nil {
		ch <- true
		close(ch)
	}

	c.wl.Lock()
	c.cancels[tag] = nil, false
	c.wl.Unlock()

	return &R{}
}

func (c *conn) watch(t *T) *R {
	pat := pb.GetString(t.Path)
	glob, err := store.CompileGlob(pat)
	if err != nil {
		return errResponse(err)
	}

	cancel := c.makeCancel(t)
	if cancel == nil {
		return tagInUse
	}

	w := store.NewWatch(c.s.St, glob)

	go func() {
		defer close(cancel)
		defer close(w.C)
		defer w.Stop()

		// TODO buffer (and possibly discard) events
		for {
			select {
			case ev := <-w.C:
				if closed(w.C) {
					return
				}
				var r R
				r.Path = &ev.Path
				r.Value = []byte(ev.Body)
				r.Cas = &ev.Cas
				err := c.respond(t, Valid, &r)
				if err != nil {
					// TODO log error
					return
				}
			case <-cancel:
				return
			}
		}
	}()

	return nil
}

func (c *conn) snap(t *T) *R {
	ver, g := c.s.St.Snap()

	var r R
	r.Seqn = pb.Int64(int64(ver))

	c.slk.Lock()
	c.sid++
	r.Id = pb.Int32(c.sid)
	c.snaps[*r.Id] = g
	c.slk.Unlock()

	return &r
}

func (c *conn) delSnap(t *T) *R {
	id := pb.GetInt32(t.Id)
	c.slk.Lock()
	c.snaps[id] = nil, false
	c.slk.Unlock()

	return &R{}
}

var ops = map[int32] func(*conn, *T) *R {
	proto.Request_CANCEL:  (*conn).cancel,
	proto.Request_DEL:     (*conn).del,
	proto.Request_DELSNAP: (*conn).delSnap,
	proto.Request_NOOP:    (*conn).noop,
	proto.Request_GET:     (*conn).get,
	proto.Request_SET:     (*conn).set,
	proto.Request_SNAP:    (*conn).snap,
	proto.Request_WATCH:   (*conn).watch,
	proto.Request_JOIN:    (*conn).join,
	proto.Request_CHECKIN: (*conn).checkin,
}

func (c *conn) serve() {
	logger := util.NewLogger("%v", c.c.RemoteAddr())
	logger.Println("accepted connection")
	for {
		t, err := c.readBuf()
		if err != nil {
			if err == os.EOF {
				logger.Println("connection closed by peer")
			} else {
				logger.Println(err)
			}
			return
		}

		rlogger := util.NewLogger("%v - req [%d]", c.c.RemoteAddr(), t.Tag)

		verb := pb.GetInt32((*int32)(t.Verb))
		f, ok := ops[verb]
		if !ok {
			rlogger.Printf("unknown verb <%d>", verb)
			var r R
			r.ErrCode = proto.NewResponse_Err(proto.Response_UNKNOWN_VERB)
			c.respond(t, Valid|Done, &r)
			continue
		}

		r := f(c, t)
		if r != nil {
			c.respond(t, Valid|Done, r)
		}
	}
}
<commit_msg>server: calculate checkin return time more accurately<commit_after>package server

import (
	dnet "doozer/net"
	"doozer/paxos"
	"doozer/proto"
	"doozer/store"
	"doozer/util"
	"encoding/binary"
	"io"
	"net"
	"os"
	pb "goprotobuf.googlecode.com/hg/proto"
	"rand"
	"strconv"
	"sync"
	"time"
)

const packetSize = 3000

const (
	sessionLease = 60e9 // ns == 60s
	sessionPad   = 5e8 // ns == .5s
)

var (
	ErrPoisoned = os.NewError("poisoned")
)

var (
	other       = proto.NewResponse_Err(proto.Response_OTHER)
	redirect    = proto.NewResponse_Err(proto.Response_REDIRECT)
	newErrCode  = proto.NewResponse_Err
	tagInUse    = &R{ErrCode: newErrCode(proto.Response_TAG_IN_USE)}
	isDir       = &R{ErrCode: newErrCode(proto.Response_ISDIR)}
	badSnap     = &R{ErrCode: newErrCode(proto.Response_INVALID_SNAP)}
	readonly    = &R{
		ErrCode: newErrCode(proto.Response_OTHER),
		ErrDetail: pb.String("no known writeable addresses"),
	}
	badTag      = &R{
		ErrCode: newErrCode(proto.Response_OTHER),
		ErrDetail: pb.String("unknown tag"),
	}
)

func errResponse(e os.Error) *R {
	return &R{ErrCode: other, ErrDetail: pb.String(e.String())}
}

// Response flags
const (
	Valid = 1 << iota
	Done
)

var slots = store.MustCompileGlob("/doozer/slot/*")

type T proto.Request
type R proto.Response

type OpError struct {
	Detail string
}

type Manager interface {
	paxos.Proposer
	ProposeOnce(v string, c chan bool) store.Event
	PutFrom(string, paxos.Msg)
	Alpha() int
}

type Server struct {
	Conn net.PacketConn
	Addr string
	St   *store.Store
	Mg   Manager
	Self string
}

func (sv *Server) ServeUdp(outs chan paxos.Packet) {
	r := dnet.Ackify(sv.Conn, outs)

	for p := range r {
		sv.Mg.PutFrom(p.Addr, p.Msg)
	}
}

var clg = util.NewLogger("cal")

func (s *Server) Serve(l net.Listener, cal chan int) os.Error {
	for {
		rw, err := l.Accept()
		if err != nil {
			if e, ok := err.(*net.OpError); ok && e.Error == os.EINVAL {
				return nil
			}
			return err
		}
		c := &conn{
			c:       rw,
			s:       s,
			cal:     closed(cal),
			snaps:   make(map[int32]store.Getter),
			cancels: make(map[int32]chan bool),
		}
		go c.serve()
	}

	panic("unreachable")
}

func (sv *Server) cals() []string {
	cals := make([]string, 0)
	_, g := sv.St.Snap()
	store.Walk(g, slots, func(_, body, _ string) {
		if len(body) > 0 {
			cals = append(cals, body)
		}
	})
	return cals
}

// Repeatedly propose nop values until a successful read from `done`.
func (sv *Server) AdvanceUntil(done chan int) {
	for _, ok := <-done; !ok; _, ok = <-done {
		sv.Mg.Propose(store.Nop, nil)
	}
}

type conn struct {
	c        net.Conn
	s        *Server
	cal      bool
	sid      int32
	snaps    map[int32]store.Getter
	slk      sync.RWMutex
	cancels  map[int32]chan bool
	wl       sync.Mutex // write lock
	poisoned bool
}

func (c *conn) readBuf() (*T, os.Error) {
	var size int32
	err := binary.Read(c.c, binary.BigEndian, &size)
	if err != nil {
		return nil, err
	}

	buf := make([]byte, size)
	_, err = io.ReadFull(c.c, buf)
	if err != nil {
		return nil, err
	}

	var t T
	err = pb.Unmarshal(buf, &t)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func (c *conn) makeCancel(t *T) chan bool {
	tag := pb.GetInt32(t.Tag)

	c.wl.Lock()
	defer c.wl.Unlock()

	if _, ok := c.cancels[tag]; ok {
		return nil
	}

	ch := make(chan bool)
	c.cancels[tag] = ch
	return ch
}

func (c *conn) cancellable(t *T, f func(chan bool) *R) *R {
	ch := make(chan *R, 1)
	cancel := c.makeCancel(t)
	if cancel == nil {
		return tagInUse
	}

	go func() { ch <- f(cancel) }()

	go func() {
		r := <-ch
		if r != nil {
			c.respond(t, Valid|Done, r)
		}
	}()

	return nil
}

func (c *conn) respond(t *T, flag int32, r *R) os.Error {
	r.Tag = t.Tag
	r.Flags = pb.Int32(flag)
	tag := pb.GetInt32(t.Tag)

	c.wl.Lock()
	defer c.wl.Unlock()

	if c.poisoned {
		return ErrPoisoned
	}

	if ch := c.cancels[tag]; ch != nil && flag&Done != 0 {
		c.cancels[tag] = nil, false
		close(ch)
	}

	buf, err := pb.Marshal(r)
	if err != nil {
		c.poisoned = true
		return err
	}

	err = binary.Write(c.c, binary.BigEndian, int32(len(buf)))
	if err != nil {
		c.poisoned = true
		return err
	}

	for len(buf) > 0 {
		n, err := c.c.Write(buf)
		if err != nil {
			c.poisoned = true
			return err
		}

		buf = buf[n:]
	}

	return nil
}

func (c *conn) redirect() *R {
	cals := c.s.cals()
	if len(cals) < 1 {
		return readonly
	}

	cal := cals[rand.Intn(len(cals))]
	parts, cas := c.s.St.Get("/doozer/info/" + cal + "/public-addr")
	if cas == store.Dir && cas == store.Missing {
		return readonly
	}

	return &R{ErrCode: redirect, ErrDetail: &parts[0]}
}

func (c *conn) get(t *T) *R {
	var g store.Getter
	id := pb.GetInt32(t.Id)
	if id == 0 {
		g = c.s.St
	} else {
		var ok bool
		c.slk.RLock()
		g, ok = c.snaps[id]
		c.slk.RUnlock()
		if !ok {
			return badSnap
		}
	}

	v, cas := g.Get(pb.GetString(t.Path))
	if cas == store.Dir {
		return isDir
	}

	var r R
	r.Cas = &cas
	if len(v) == 1 { // not missing
		r.Value = []byte(v[0])
	}
	return &r
}

func (c *conn) set(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		_, cas, err := paxos.Set(c.s.Mg, *t.Path, string(t.Value), *t.Cas, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		return &R{Cas: &cas}
	})
}

func (c *conn) del(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		err := paxos.Del(c.s.Mg, *t.Path, *t.Cas, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		return &R{}
	})
}

func (c *conn) noop(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		ev := c.s.Mg.ProposeOnce(store.Nop, cancel)
		if ev.Err == paxos.ErrCancel {
			return nil
		}
		return &R{}
	})
}

func (c *conn) join(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		key := "/doozer/members/" + pb.GetString(t.Path)
		seqn, _, err := paxos.Set(c.s.Mg, key, string(t.Value), store.Missing, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		done := make(chan int)
		go c.s.AdvanceUntil(done)
		c.s.St.Sync(seqn + uint64(c.s.Mg.Alpha()))
		close(done)
		seqn, snap := c.s.St.Snapshot()
		seqn1 := int64(seqn)
		return &R{Seqn: &seqn1, Value: []byte(snap)}
	})
}

func (c *conn) checkin(t *T) *R {
	if !c.cal {
		return c.redirect()
	}

	return c.cancellable(t, func(cancel chan bool) *R {
		deadline := time.Nanoseconds() + sessionLease
		body := strconv.Itoa64(deadline)
		sess := pb.GetString(t.Path)
		cas := pb.GetString(t.Cas)
		_, cas, err := paxos.Set(c.s.Mg, "/session/"+sess, body, cas, cancel)
		if err == paxos.ErrCancel {
			return nil
		}
		if err != nil {
			return errResponse(err)
		}

		select {
		case <-time.After(deadline - sessionPad - time.Nanoseconds()):
		case <-cancel:
			return nil
		}
		return &R{Cas: &cas}
	})
}

func (c *conn) cancel(t *T) *R {
	tag := pb.GetInt32(t.Id)

	c.wl.Lock()
	ch := c.cancels[tag]
	c.wl.Unlock()

	if ch != nil {
		ch <- true
		close(ch)
	}

	c.wl.Lock()
	c.cancels[tag] = nil, false
	c.wl.Unlock()

	return &R{}
}

func (c *conn) watch(t *T) *R {
	pat := pb.GetString(t.Path)
	glob, err := store.CompileGlob(pat)
	if err != nil {
		return errResponse(err)
	}

	cancel := c.makeCancel(t)
	if cancel == nil {
		return tagInUse
	}

	w := store.NewWatch(c.s.St, glob)

	go func() {
		defer close(cancel)
		defer close(w.C)
		defer w.Stop()

		// TODO buffer (and possibly discard) events
		for {
			select {
			case ev := <-w.C:
				if closed(w.C) {
					return
				}
				var r R
				r.Path = &ev.Path
				r.Value = []byte(ev.Body)
				r.Cas = &ev.Cas
				err := c.respond(t, Valid, &r)
				if err != nil {
					// TODO log error
					return
				}
			case <-cancel:
				return
			}
		}
	}()

	return nil
}

func (c *conn) snap(t *T) *R {
	ver, g := c.s.St.Snap()

	var r R
	r.Seqn = pb.Int64(int64(ver))

	c.slk.Lock()
	c.sid++
	r.Id = pb.Int32(c.sid)
	c.snaps[*r.Id] = g
	c.slk.Unlock()

	return &r
}

func (c *conn) delSnap(t *T) *R {
	id := pb.GetInt32(t.Id)
	c.slk.Lock()
	c.snaps[id] = nil, false
	c.slk.Unlock()

	return &R{}
}

var ops = map[int32] func(*conn, *T) *R {
	proto.Request_CANCEL:  (*conn).cancel,
	proto.Request_DEL:     (*conn).del,
	proto.Request_DELSNAP: (*conn).delSnap,
	proto.Request_NOOP:    (*conn).noop,
	proto.Request_GET:     (*conn).get,
	proto.Request_SET:     (*conn).set,
	proto.Request_SNAP:    (*conn).snap,
	proto.Request_WATCH:   (*conn).watch,
	proto.Request_JOIN:    (*conn).join,
	proto.Request_CHECKIN: (*conn).checkin,
}

func (c *conn) serve() {
	logger := util.NewLogger("%v", c.c.RemoteAddr())
	logger.Println("accepted connection")
	for {
		t, err := c.readBuf()
		if err != nil {
			if err == os.EOF {
				logger.Println("connection closed by peer")
			} else {
				logger.Println(err)
			}
			return
		}

		rlogger := util.NewLogger("%v - req [%d]", c.c.RemoteAddr(), t.Tag)

		verb := pb.GetInt32((*int32)(t.Verb))
		f, ok := ops[verb]
		if !ok {
			rlogger.Printf("unknown verb <%d>", verb)
			var r R
			r.ErrCode = proto.NewResponse_Err(proto.Response_UNKNOWN_VERB)
			c.respond(t, Valid|Done, &r)
			continue
		}

		r := f(c, t)
		if r != nil {
			c.respond(t, Valid|Done, r)
		}
	}
}
<|endoftext|>


<commit_before>package backoff

import (
	"context"
	"time"
)

// BackOffContext is a backoff policy that stops retrying after the context
// is canceled.
type BackOffContext interface { // nolint: golint
	BackOff
	Context() context.Context
}

type backOffContext struct {
	BackOff
	ctx context.Context
}

// WithContext returns a BackOffContext with context ctx
//
// ctx must not be nil
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
	if ctx == nil {
		panic("nil context")
	}

	if b, ok := b.(*backOffContext); ok {
		return &backOffContext{
			BackOff: b.BackOff,
			ctx:     ctx,
		}
	}

	return &backOffContext{
		BackOff: b,
		ctx:     ctx,
	}
}

func ensureContext(b BackOff) BackOffContext {
	if cb, ok := b.(BackOffContext); ok {
		return cb
	}
	return WithContext(b, context.Background())
}

func (b *backOffContext) Context() context.Context {
	return b.ctx
}

func (b *backOffContext) NextBackOff() time.Duration {
	select {
	case <-b.ctx.Done():
		return Stop
	default:
	}
	next := b.BackOff.NextBackOff()
	if deadline, ok := b.ctx.Deadline(); ok && time.Until(deadline) < next {
		return Stop
	}
	return next
}
<commit_msg>time.Until not available in go 1.7<commit_after>package backoff

import (
	"context"
	"time"
)

// BackOffContext is a backoff policy that stops retrying after the context
// is canceled.
type BackOffContext interface { // nolint: golint
	BackOff
	Context() context.Context
}

type backOffContext struct {
	BackOff
	ctx context.Context
}

// WithContext returns a BackOffContext with context ctx
//
// ctx must not be nil
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
	if ctx == nil {
		panic("nil context")
	}

	if b, ok := b.(*backOffContext); ok {
		return &backOffContext{
			BackOff: b.BackOff,
			ctx:     ctx,
		}
	}

	return &backOffContext{
		BackOff: b,
		ctx:     ctx,
	}
}

func ensureContext(b BackOff) BackOffContext {
	if cb, ok := b.(BackOffContext); ok {
		return cb
	}
	return WithContext(b, context.Background())
}

func (b *backOffContext) Context() context.Context {
	return b.ctx
}

func (b *backOffContext) NextBackOff() time.Duration {
	select {
	case <-b.ctx.Done():
		return Stop
	default:
	}
	next := b.BackOff.NextBackOff()
	if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { // nolint: gosimple
		return Stop
	}
	return next
}
<|endoftext|>


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

package context

import (
	"net/http"
	"sync"
	"time"
)

var globalContext *Context = NewContext()

type Context struct {
	mutex sync.RWMutex
	data  map[*http.Request]map[interface{}]interface{}
	datat map[*http.Request]int64
}

func NewContext() *Context {
	data := make(map[*http.Request]map[interface{}]interface{})
	datat := make(map[*http.Request]int64)
	return &Context{data: data, datat: datat}
}

// Set stores a value for a given key in a given request.
func Set(r *http.Request, key, val interface{}) {
	globalContext.Set(r, key, val)
}

func (c *Context) Set(r *http.Request, key, val interface{}) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	if c.data[r] == nil {
		c.data[r] = make(map[interface{}]interface{})
		c.datat[r] = time.Now().Unix()
	}
	c.data[r][key] = val
}

// Get returns a value stored for a given key in a given request.
func Get(r *http.Request, key interface{}) interface{} {
	return globalContext.Get(r, key)
}

func (c *Context) Get(r *http.Request, key interface{}) interface{} {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	if c.data[r] != nil {
		return c.data[r][key]
	}
	return nil
}

// Delete removes a value stored for a given key in a given request.
func Delete(r *http.Request, key interface{}) {
	globalContext.Delete(r, key)
}

func (c *Context) Delete(r *http.Request, key interface{}) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	if c.data[r] != nil {
		delete(c.data[r], key)
	}
}

// Clear removes all values stored for a given request.
//
// This is usually called by a handler wrapper to clean up request
// variables at the end of a request lifetime. See ClearHandler().
func Clear(r *http.Request) {
	globalContext.Clear(r)
}

func (c *Context) Clear(r *http.Request) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.clear(r)
}

// clear is Clear without the lock.
func (c *Context) clear(r *http.Request) {
	delete(c.data, r)
	delete(c.datat, r)
}

// Purge removes request data stored for longer than maxAge, in seconds.
// It returns the amount of requests removed.
//
// If maxAge <= 0, all request data is removed.
//
// This is only used for sanity check: in case context cleaning was not
// properly set some request data can be kept forever, consuming an increasing
// amount of memory. In case this is detected, Purge() must be called
// periodically until the problem is fixed.
func Purge(maxAge int) int {
	return globalContext.Purge(maxAge)
}

func (c *Context) Purge(maxAge int) int {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	count := 0
	if maxAge <= 0 {
		count = len(c.data)
		c.data = make(map[*http.Request]map[interface{}]interface{})
		c.datat = make(map[*http.Request]int64)
	} else {
		min := time.Now().Unix() - int64(maxAge)
		for r, _ := range c.data {
			if c.datat[r] < min {
				c.clear(r)
				count++
			}
		}
	}
	return count
}

// ClearHandler wraps an http.Handler and clears request values at the end
// of a request lifetime.
func ClearHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer Clear(r)
		h.ServeHTTP(w, r)
	})
}
<commit_msg>Revert "Added a Context type for non-global contexts."<commit_after>// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package context

import (
	"net/http"
	"sync"
	"time"
)

var (
	mutex sync.Mutex
	data  = make(map[*http.Request]map[interface{}]interface{})
	datat = make(map[*http.Request]int64)
)

// Set stores a value for a given key in a given request.
func Set(r *http.Request, key, val interface{}) {
	mutex.Lock()
	defer mutex.Unlock()
	if data[r] == nil {
		data[r] = make(map[interface{}]interface{})
		datat[r] = time.Now().Unix()
	}
	data[r][key] = val
}

// Get returns a value stored for a given key in a given request.
func Get(r *http.Request, key interface{}) interface{} {
	mutex.Lock()
	defer mutex.Unlock()
	if data[r] != nil {
		return data[r][key]
	}
	return nil
}

// Delete removes a value stored for a given key in a given request.
func Delete(r *http.Request, key interface{}) {
	mutex.Lock()
	defer mutex.Unlock()
	if data[r] != nil {
		delete(data[r], key)
	}
}

// Clear removes all values stored for a given request.
//
// This is usually called by a handler wrapper to clean up request
// variables at the end of a request lifetime. See ClearHandler().
func Clear(r *http.Request) {
	mutex.Lock()
	defer mutex.Unlock()
	clear(r)
}

// clear is Clear without the lock.
func clear(r *http.Request) {
	delete(data, r)
	delete(datat, r)
}

// Purge removes request data stored for longer than maxAge, in seconds.
// It returns the amount of requests removed.
//
// If maxAge <= 0, all request data is removed.
//
// This is only used for sanity check: in case context cleaning was not
// properly set some request data can be kept forever, consuming an increasing
// amount of memory. In case this is detected, Purge() must be called
// periodically until the problem is fixed.
func Purge(maxAge int) int {
	mutex.Lock()
	defer mutex.Unlock()
	count := 0
	if maxAge <= 0 {
		count = len(data)
		data = make(map[*http.Request]map[interface{}]interface{})
		datat = make(map[*http.Request]int64)
	} else {
		min := time.Now().Unix() - int64(maxAge)
		for r, _ := range data {
			if datat[r] < min {
				clear(r)
				count++
			}
		}
	}
	return count
}

// ClearHandler wraps an http.Handler and clears request values at the end
// of a request lifetime.
func ClearHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer Clear(r)
		h.ServeHTTP(w, r)
	})
}
<|endoftext|>


<commit_before>package cli

import (
	"errors"
	"flag"
	"os"
	"reflect"
	"strings"
)

// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
	App           *App
	Command       Command
	flagSet       *flag.FlagSet
	setFlags      map[string]bool
	parentContext *Context
}

// NewContext creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
	return &Context{App: app, flagSet: set, parentContext: parentCtx}
}

// NumFlags returns the number of flags set
func (c *Context) NumFlags() int {
	return c.flagSet.NFlag()
}

// Set sets a context flag to a value.
func (c *Context) Set(name, value string) error {
	return c.flagSet.Set(name, value)
}

// GlobalSet sets a context flag to a value on the global flagset
func (c *Context) GlobalSet(name, value string) error {
	return globalContext(c).flagSet.Set(name, value)
}

// IsSet determines if the flag was actually set
func (c *Context) IsSet(name string) bool {
	if c.setFlags == nil {
		c.setFlags = make(map[string]bool)

		c.flagSet.Visit(func(f *flag.Flag) {
			c.setFlags[f.Name] = true
		})

		c.flagSet.VisitAll(func(f *flag.Flag) {
			if _, ok := c.setFlags[f.Name]; ok {
				return
			}
			c.setFlags[f.Name] = false
		})

		// XXX hack to support IsSet for flags with EnvVar
		//
		// There isn't an easy way to do this with the current implementation since
		// whether a flag was set via an environment variable is very difficult to
		// determine here. Instead, we intend to introduce a backwards incompatible
		// change in version 2 to add `IsSet` to the Flag interface to push the
		// responsibility closer to where the information required to determine
		// whether a flag is set by non-standard means such as environment
		// variables is avaliable.
		//
		// See https://github.com/urfave/cli/issues/294 for additional discussion
		flags := c.Command.Flags
		if c.Command.Name == "" { // cannot == Command{} since it contains slice types
			if c.App != nil {
				flags = c.App.Flags
			}
		}
		for _, f := range flags {
			eachName(f.GetName(), func(name string) {
				if isSet, ok := c.setFlags[name]; isSet || !ok {
					return
				}

				envVarValue := reflect.ValueOf(f).FieldByName("EnvVar")
				if !envVarValue.IsValid() {
					return
				}

				eachName(envVarValue.String(), func(envVar string) {
					envVar = strings.TrimSpace(envVar)
					if envVal := os.Getenv(envVar); envVal != "" {
						c.setFlags[name] = true
						return
					}
				})
			})
		}
	}

	return c.setFlags[name]
}

// GlobalIsSet determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool {
	ctx := c
	if ctx.parentContext != nil {
		ctx = ctx.parentContext
	}

	for ; ctx != nil; ctx = ctx.parentContext {
		if ctx.IsSet(name) {
			return true
		}
	}
	return false
}

// FlagNames returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) {
	for _, flag := range c.Command.Flags {
		name := strings.Split(flag.GetName(), ",")[0]
		if name == "help" {
			continue
		}
		names = append(names, name)
	}
	return
}

// GlobalFlagNames returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) {
	for _, flag := range c.App.Flags {
		name := strings.Split(flag.GetName(), ",")[0]
		if name == "help" || name == "version" {
			continue
		}
		names = append(names, name)
	}
	return
}

// Parent returns the parent context, if any
func (c *Context) Parent() *Context {
	return c.parentContext
}

// Args contains apps console arguments
type Args []string

// Args returns the command line arguments associated with the context.
func (c *Context) Args() Args {
	args := Args(c.flagSet.Args())
	return args
}

// NArg returns the number of the command line arguments.
func (c *Context) NArg() int {
	return len(c.Args())
}

// Get returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
	if len(a) > n {
		return a[n]
	}
	return ""
}

// First returns the first argument, or else a blank string
func (a Args) First() string {
	return a.Get(0)
}

// Tail returns the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
	if len(a) >= 2 {
		return []string(a)[1:]
	}
	return []string{}
}

// Present checks if there are any arguments present
func (a Args) Present() bool {
	return len(a) != 0
}

// Swap swaps arguments at the given indexes
func (a Args) Swap(from, to int) error {
	if from >= len(a) || to >= len(a) {
		return errors.New("index out of range")
	}
	a[from], a[to] = a[to], a[from]
	return nil
}

func globalContext(ctx *Context) *Context {
	if ctx == nil {
		return nil
	}

	for {
		if ctx.parentContext == nil {
			return ctx
		}
		ctx = ctx.parentContext
	}
}

func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
	if ctx.parentContext != nil {
		ctx = ctx.parentContext
	}
	for ; ctx != nil; ctx = ctx.parentContext {
		if f := ctx.flagSet.Lookup(name); f != nil {
			return ctx.flagSet
		}
	}
	return nil
}

func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
	switch ff.Value.(type) {
	case *StringSlice:
	default:
		set.Set(name, ff.Value.String())
	}
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
	visited := make(map[string]bool)
	set.Visit(func(f *flag.Flag) {
		visited[f.Name] = true
	})
	for _, f := range flags {
		parts := strings.Split(f.GetName(), ",")
		if len(parts) == 1 {
			continue
		}
		var ff *flag.Flag
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if visited[name] {
				if ff != nil {
					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
				}
				ff = set.Lookup(name)
			}
		}
		if ff == nil {
			continue
		}
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if !visited[name] {
				copyFlag(name, ff, set)
			}
		}
	}
	return nil
}
<commit_msg>Dereference `Flag`s if they are pointers<commit_after>package cli

import (
	"errors"
	"flag"
	"os"
	"reflect"
	"strings"
)

// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
	App           *App
	Command       Command
	flagSet       *flag.FlagSet
	setFlags      map[string]bool
	parentContext *Context
}

// NewContext creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
	return &Context{App: app, flagSet: set, parentContext: parentCtx}
}

// NumFlags returns the number of flags set
func (c *Context) NumFlags() int {
	return c.flagSet.NFlag()
}

// Set sets a context flag to a value.
func (c *Context) Set(name, value string) error {
	return c.flagSet.Set(name, value)
}

// GlobalSet sets a context flag to a value on the global flagset
func (c *Context) GlobalSet(name, value string) error {
	return globalContext(c).flagSet.Set(name, value)
}

// IsSet determines if the flag was actually set
func (c *Context) IsSet(name string) bool {
	if c.setFlags == nil {
		c.setFlags = make(map[string]bool)

		c.flagSet.Visit(func(f *flag.Flag) {
			c.setFlags[f.Name] = true
		})

		c.flagSet.VisitAll(func(f *flag.Flag) {
			if _, ok := c.setFlags[f.Name]; ok {
				return
			}
			c.setFlags[f.Name] = false
		})

		// XXX hack to support IsSet for flags with EnvVar
		//
		// There isn't an easy way to do this with the current implementation since
		// whether a flag was set via an environment variable is very difficult to
		// determine here. Instead, we intend to introduce a backwards incompatible
		// change in version 2 to add `IsSet` to the Flag interface to push the
		// responsibility closer to where the information required to determine
		// whether a flag is set by non-standard means such as environment
		// variables is avaliable.
		//
		// See https://github.com/urfave/cli/issues/294 for additional discussion
		flags := c.Command.Flags
		if c.Command.Name == "" { // cannot == Command{} since it contains slice types
			if c.App != nil {
				flags = c.App.Flags
			}
		}
		for _, f := range flags {
			eachName(f.GetName(), func(name string) {
				if isSet, ok := c.setFlags[name]; isSet || !ok {
					return
				}

				val := reflect.ValueOf(f)
				if val.Kind() == reflect.Ptr {
					val = val.Elem()
				}

				envVarValue := val.FieldByName("EnvVar")
				if !envVarValue.IsValid() {
					return
				}

				eachName(envVarValue.String(), func(envVar string) {
					envVar = strings.TrimSpace(envVar)
					if envVal := os.Getenv(envVar); envVal != "" {
						c.setFlags[name] = true
						return
					}
				})
			})
		}
	}

	return c.setFlags[name]
}

// GlobalIsSet determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool {
	ctx := c
	if ctx.parentContext != nil {
		ctx = ctx.parentContext
	}

	for ; ctx != nil; ctx = ctx.parentContext {
		if ctx.IsSet(name) {
			return true
		}
	}
	return false
}

// FlagNames returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) {
	for _, flag := range c.Command.Flags {
		name := strings.Split(flag.GetName(), ",")[0]
		if name == "help" {
			continue
		}
		names = append(names, name)
	}
	return
}

// GlobalFlagNames returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) {
	for _, flag := range c.App.Flags {
		name := strings.Split(flag.GetName(), ",")[0]
		if name == "help" || name == "version" {
			continue
		}
		names = append(names, name)
	}
	return
}

// Parent returns the parent context, if any
func (c *Context) Parent() *Context {
	return c.parentContext
}

// Args contains apps console arguments
type Args []string

// Args returns the command line arguments associated with the context.
func (c *Context) Args() Args {
	args := Args(c.flagSet.Args())
	return args
}

// NArg returns the number of the command line arguments.
func (c *Context) NArg() int {
	return len(c.Args())
}

// Get returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
	if len(a) > n {
		return a[n]
	}
	return ""
}

// First returns the first argument, or else a blank string
func (a Args) First() string {
	return a.Get(0)
}

// Tail returns the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
	if len(a) >= 2 {
		return []string(a)[1:]
	}
	return []string{}
}

// Present checks if there are any arguments present
func (a Args) Present() bool {
	return len(a) != 0
}

// Swap swaps arguments at the given indexes
func (a Args) Swap(from, to int) error {
	if from >= len(a) || to >= len(a) {
		return errors.New("index out of range")
	}
	a[from], a[to] = a[to], a[from]
	return nil
}

func globalContext(ctx *Context) *Context {
	if ctx == nil {
		return nil
	}

	for {
		if ctx.parentContext == nil {
			return ctx
		}
		ctx = ctx.parentContext
	}
}

func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
	if ctx.parentContext != nil {
		ctx = ctx.parentContext
	}
	for ; ctx != nil; ctx = ctx.parentContext {
		if f := ctx.flagSet.Lookup(name); f != nil {
			return ctx.flagSet
		}
	}
	return nil
}

func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
	switch ff.Value.(type) {
	case *StringSlice:
	default:
		set.Set(name, ff.Value.String())
	}
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
	visited := make(map[string]bool)
	set.Visit(func(f *flag.Flag) {
		visited[f.Name] = true
	})
	for _, f := range flags {
		parts := strings.Split(f.GetName(), ",")
		if len(parts) == 1 {
			continue
		}
		var ff *flag.Flag
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if visited[name] {
				if ff != nil {
					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
				}
				ff = set.Lookup(name)
			}
		}
		if ff == nil {
			continue
		}
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if !visited[name] {
				copyFlag(name, ff, set)
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Marcel Gotsch. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package goserv

import "net/http"

// RequestContext stores key-value pairs supporting all data types and
// capture URL parameter values accessible by their parameter name.
type RequestContext struct {
	store  anyMap
	params params
	err    *ContextError
}

// Set sets the value for the specified the key. It replaces any existing values.
func (c *RequestContext) Set(key string, value interface{}) {
	c.store[key] = value
}

// Get retrieves the value for key. If the key doesn't exist in the RequestContext,
// Get returns nil.
func (c *RequestContext) Get(key string) interface{} {
	return c.store[key]
}

// Delete deletes the value associated with key. If the key doesn't exist nothing happens.
func (c *RequestContext) Delete(key string) {
	delete(c.store, key)
}

// Exists returns true if the specified key exists in the RequestContext, otherwise false is returned.
func (c *RequestContext) Exists(key string) bool {
	_, exists := c.store[key]
	return exists
}

// Param returns the capture URL parameter value for the given parameter name. The name is
// the one specified in one of the routing functions without the leading ":".
func (c *RequestContext) Param(name string) string {
	return c.params[name]
}

// Error sets a ContextError which will be passed to the next error handler.
// Calling Error twice will cause a runtime panic!
func (c *RequestContext) Error(err error, code int) {
	if c.err != nil {
		panic("RequestContext: called .Error() twice")
	}
	c.err = &ContextError{err, code}
}

func newRequestContext() *RequestContext {
	return &RequestContext{
		store:  make(anyMap),
		params: make(params),
		err:    nil,
	}
}

// Stores a RequestContext for each Request.
var requestContextMap = make(map[*http.Request]*RequestContext)

// Context returns the corresponding RequestContext for the given Request.
func Context(r *http.Request) *RequestContext {
	return requestContextMap[r]
}

// Stores a new RequestContext for the specified Request in the requestContextMap.
// This may overwrite an existing RequestContext!
func createRequestContext(r *http.Request) {
	requestContextMap[r] = newRequestContext()
}

type params map[string]string
type anyMap map[string]interface{}
<commit_msg>Fix wrong receiver var name<commit_after>// Copyright 2016 Marcel Gotsch. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package goserv

import "net/http"

// RequestContext stores key-value pairs supporting all data types and
// capture URL parameter values accessible by their parameter name.
type RequestContext struct {
	store  anyMap
	params params
	err    *ContextError
}

// Set sets the value for the specified the key. It replaces any existing values.
func (r *RequestContext) Set(key string, value interface{}) {
	r.store[key] = value
}

// Get retrieves the value for key. If the key doesn't exist in the RequestContext,
// Get returns nil.
func (r *RequestContext) Get(key string) interface{} {
	return r.store[key]
}

// Delete deletes the value associated with key. If the key doesn't exist nothing happens.
func (r *RequestContext) Delete(key string) {
	delete(r.store, key)
}

// Exists returns true if the specified key exists in the RequestContext, otherwise false is returned.
func (r *RequestContext) Exists(key string) bool {
	_, exists := r.store[key]
	return exists
}

// Param returns the capture URL parameter value for the given parameter name. The name is
// the one specified in one of the routing functions without the leading ":".
func (r *RequestContext) Param(name string) string {
	return r.params[name]
}

// Error sets a ContextError which will be passed to the next error handler.
// Calling Error twice will cause a runtime panic!
func (r *RequestContext) Error(err error, code int) {
	if r.err != nil {
		panic("RequestContext: called .Error() twice")
	}
	r.err = &ContextError{err, code}
}

func newRequestContext() *RequestContext {
	return &RequestContext{
		store:  make(anyMap),
		params: make(params),
		err:    nil,
	}
}

// Stores a RequestContext for each Request.
var requestContextMap = make(map[*http.Request]*RequestContext)

// Context returns the corresponding RequestContext for the given Request.
func Context(r *http.Request) *RequestContext {
	return requestContextMap[r]
}

// Stores a new RequestContext for the specified Request in the requestContextMap.
// This may overwrite an existing RequestContext!
func createRequestContext(r *http.Request) {
	requestContextMap[r] = newRequestContext()
}

type params map[string]string
type anyMap map[string]interface{}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Xuyuan Pang
 * Author: Pang Xuyuan <xuyuanp # gmail dot com>
 *
 * 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 hador

import (
	"net/http"
	"sync"
)

// Context struct
type Context struct {
	Request         *http.Request
	Response        ResponseWriter
	Params          Params
	NotFoundHandler http.Handler
	data            map[string]interface{}
	Logger          Logger
	mutex           sync.RWMutex
}

func NewContext(w http.ResponseWriter, req *http.Request, logger Logger) *Context {
	return &Context{
		Request:  req,
		Response: NewResponseWriter(w),
		Params:   make(Params),
		data:     make(map[string]interface{}),
		Logger:   logger,
	}
}

func (ctx *Context) NotFound() {
	if ctx.NotFoundHandler == nil {
		http.NotFound(ctx.Response, ctx.Request)
		return
	}
	ctx.NotFoundHandler.ServeHTTP(ctx.Response, ctx.Request)
}

func (ctx *Context) Set(key string, value interface{}) {
	ctx.mutex.Lock()
	defer ctx.mutex.Unlock()
	ctx.data[key] = value
}

func (ctx *Context) Get(key string) interface{} {
	ctx.mutex.RLock()
	defer ctx.mutex.RUnlock()
	if v, ok := ctx.data[key]; ok {
		return v
	}
	return nil
}

func (ctx *Context) GetOK(key string) (value interface{}, ok bool) {
	ctx.mutex.RLock()
	defer ctx.mutex.RUnlock()
	if v, ok := ctx.data[key]; ok {
		return v, true
	}
	return nil, false
}

func (ctx *Context) Delete(key string) interface{} {
	ctx.mutex.Lock()
	defer ctx.mutex.Unlock()
	if v, ok := ctx.data[key]; ok {
		delete(ctx.data, key)
		return v
	}
	return nil
}
<commit_msg>Use custom handler<commit_after>/*
 * Copyright 2015 Xuyuan Pang
 * Author: Pang Xuyuan <xuyuanp # gmail dot com>
 *
 * 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 hador

import (
	"net/http"
	"sync"
)

// Context struct
type Context struct {
	Request         *http.Request
	Response        ResponseWriter
	Params          Params
	NotFoundHandler Handler
	data            map[string]interface{}
	Logger          Logger
	mutex           sync.RWMutex
}

func NewContext(w http.ResponseWriter, req *http.Request, logger Logger) *Context {
	return &Context{
		Request:  req,
		Response: NewResponseWriter(w),
		Params:   make(Params),
		data:     make(map[string]interface{}),
		Logger:   logger,
	}
}

func (ctx *Context) NotFound() {
	if ctx.NotFoundHandler == nil {
		http.NotFound(ctx.Response, ctx.Request)
		return
	}
	ctx.NotFoundHandler.Serve(ctx)
}

func (ctx *Context) Set(key string, value interface{}) {
	ctx.mutex.Lock()
	defer ctx.mutex.Unlock()
	ctx.data[key] = value
}

func (ctx *Context) Get(key string) interface{} {
	ctx.mutex.RLock()
	defer ctx.mutex.RUnlock()
	if v, ok := ctx.data[key]; ok {
		return v
	}
	return nil
}

func (ctx *Context) GetOK(key string) (value interface{}, ok bool) {
	ctx.mutex.RLock()
	defer ctx.mutex.RUnlock()
	if v, ok := ctx.data[key]; ok {
		return v, true
	}
	return nil, false
}

func (ctx *Context) Delete(key string) interface{} {
	ctx.mutex.Lock()
	defer ctx.mutex.Unlock()
	if v, ok := ctx.data[key]; ok {
		delete(ctx.data, key)
		return v
	}
	return nil
}
<|endoftext|>


<commit_before>package modata

import "testing"
import "fmt"
import "time"

func TestSetup(t *testing.T) {
    fmt.Println("Test: Basic setup of clients and servers")
}

func TestBlock(t *testing.T) {
    fmt.Println("Test: Local Block service is correct")
    bs := StartBlockServer("localhost:1234")

    time.Sleep(2 * time.Second)
    fmt.Println(bs)

    b := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    c := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
    d := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1}

    status, data, contact := JsonGet("http://localhost:1234/find-value/foo", Contact{})
    if (status != NOTFOUND) {
        fmt.Println(data)
        t.Errorf("Nonexistent key exists\n")
    }

    status, data, contact = JsonPostUrl("http://localhost:1234/store?key=foo&data=bar",
                                        Contact{b, "localhost", 3333})
    if (status != OK) {
        t.Errorf("Could not post\n")
    }

    status, data, contact = JsonGet("http://localhost:1234/find-value/foo", Contact{})
    if (status != OK && data != "bar") {
        t.Errorf("Incorrect data exists\n")
    }
    fmt.Println(contact)

    status, data, contact = JsonGet("http://localhost:1234/ping", Contact{})

    // a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    ct := Contact{b, "", 0}
    bs.routingTable.Update(ct)
    ct.Port = 1
    bs.routingTable.Update(ct)

    ct.ID = c
    bs.routingTable.Update(ct)

    ct.ID = d
    bs.routingTable.Update(ct)

    status, data, contact = JsonGet("http://localhost:1234/find-node/400000000000000000000000000000000000000000", Contact{})
    fmt.Printf("Find node: %v\n", MakeContactList(data.([]interface{})))

    fmt.Println("... Pass")
}

func xTestReplication(t *testing.T) {
    fmt.Println("Test: Initialization of replication service is correct")
    rs := StartReplicationServer("localhost:8080")
    rs2 := StartReplicationServer("localhost:8081")
    fmt.Println(rs)
    fmt.Println(rs2)
    time.Sleep(100 * time.Second)
    fmt.Println("... Pass")
}

func TestDistance(t *testing.T) {
    fmt.Println("Test: Distance function between Nodes")
    a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    b := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}

    c := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    if Distance(&a, &b) != c {
        t.Errorf("XOR: %v\n", Distance(&a, &b))
    }
    fmt.Println("... Pass")
}

func TestBucketing(t *testing.T) {
    fmt.Println("Test: Bucketing")
    a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    b := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    rt := RoutingTable{}
    rt.me = a
    fmt.Printf("Bucket %d\n", rt.BucketForNode(b))
    fmt.Println("... Pass")
}

func TestExampleUpdate(t *testing.T) {
    fmt.Println("Test: Update")
    a := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    b := NodeID{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    rt := RoutingTable{}
    rt.k = 20
    rt.me = a

    c1 := Contact{b, "", 0}
    rt.Update(c1)

    // Make sure
    fmt.Printf("Update 1: Size of bucket 1: %d\n", rt.buckets[1].Len())

    c2 := Contact{b, "", 0}
    rt.Update(c2)

    fmt.Printf("Update 2: Size of bucket 1: %d\n", rt.buckets[1].Len())

    fmt.Println("... Pass")
    // Output: Update 1: Size of bucket 1: 1
    // Update 2: Size of bucket 1: 1
}

func TestShortlist(t *testing.T) {
    fmt.Println("Test: Shortlist")

    a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    k := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    b := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}

    c := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}

    d := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1}

    rt := RoutingTable{}
    rt.k = 20
    rt.me = a

    ct := Contact{b, "", 0}
    rt.Update(ct)
    ct.Port = 1
    rt.Update(ct)

    ct.ID = c
    rt.Update(ct)

    ct.ID = d
    rt.Update(ct)

    fmt.Printf("%v\n", rt.buckets[1].Front().Value);

    fmt.Printf("%v\n", rt.FindClosest(k, 4))

    fmt.Println("... Pass")
}
<commit_msg>Actually unbreaking tests ... gahh merge conflicts<commit_after>package modata

import "testing"
import "fmt"
import "time"

func TestSetup(t *testing.T) {
    fmt.Println("Test: Basic setup of clients and servers")
}

func TestBlock(t *testing.T) {
    fmt.Println("Test: Local Block service is correct")
    bs := StartBlockServer("localhost:1234")

    time.Sleep(2 * time.Second)
    fmt.Println(bs)

    b := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    c := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
    d := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1}

    status, data, contact := JsonGet("http://localhost:1234/find-value/foo", Contact{})
    if (status != NOTFOUND) {
        fmt.Println(data)
        t.Errorf("Nonexistent key exists\n")
    }

    status, data, contact = JsonPostUrl("http://localhost:1234/store?key=foo&data=bar",
                                        Contact{b, "localhost", 3333})
    if (status != OK) {
        t.Errorf("Could not post\n")
    }

    status, data, contact = JsonGet("http://localhost:1234/find-value/foo", Contact{})
    if (status != OK && data != "bar") {
        t.Errorf("Incorrect data exists\n")
    }
    fmt.Println(contact)

    status, data, contact = JsonGet("http://localhost:1234/ping", Contact{})

    // a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    ct := Contact{b, "", 0}
    bs.routingTable.Update(ct)
    ct.Port = 1
    bs.routingTable.Update(ct)

    ct.ID = c
    bs.routingTable.Update(ct)

    ct.ID = d
    bs.routingTable.Update(ct)

    status, data, contact = JsonGet("http://localhost:1234/find-node/400000000000000000000000000000000000000000", Contact{})

    fmt.Println("... Pass")
}

func xTestReplication(t *testing.T) {
    fmt.Println("Test: Initialization of replication service is correct")
    rs := StartReplicationServer("localhost:8080")
    rs2 := StartReplicationServer("localhost:8081")
    fmt.Println(rs)
    fmt.Println(rs2)
    time.Sleep(100 * time.Second)
    fmt.Println("... Pass")
}

func TestDistance(t *testing.T) {
    fmt.Println("Test: Distance function between Nodes")
    a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    b := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}

    c := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    if Distance(&a, &b) != c {
        t.Errorf("XOR: %v\n", Distance(&a, &b))
    }
    fmt.Println("... Pass")
}

func TestBucketing(t *testing.T) {
    fmt.Println("Test: Bucketing")
    a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    b := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    rt := RoutingTable{}
    rt.me = a
    fmt.Printf("Bucket %d\n", rt.BucketForNode(b))
    fmt.Println("... Pass")
}

func TestExampleUpdate(t *testing.T) {
    fmt.Println("Test: Update")
    a := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    b := NodeID{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    rt := RoutingTable{}
    rt.k = 20
    rt.me = a

    c1 := Contact{b, "", 0}
    rt.Update(c1)

    // Make sure
    fmt.Printf("Update 1: Size of bucket 1: %d\n", rt.buckets[1].Len())

    c2 := Contact{b, "", 0}
    rt.Update(c2)

    fmt.Printf("Update 2: Size of bucket 1: %d\n", rt.buckets[1].Len())

    fmt.Println("... Pass")
    // Output: Update 1: Size of bucket 1: 1
    // Update 2: Size of bucket 1: 1
}

func TestShortlist(t *testing.T) {
    fmt.Println("Test: Shortlist")

    a := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    k := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    b := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}

    c := NodeID{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}

    d := NodeID{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1}

    rt := RoutingTable{}
    rt.k = 20
    rt.me = a

    ct := Contact{b, "", 0}
    rt.Update(ct)
    ct.Port = 1
    rt.Update(ct)

    ct.ID = c
    rt.Update(ct)

    ct.ID = d
    rt.Update(ct)

    fmt.Printf("%v\n", rt.buckets[1].Front().Value);

    fmt.Printf("%v\n", rt.FindClosest(k, 4))

    fmt.Println("... Pass")
}
<|endoftext|>