<commit_before>package eval

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/elves/elvish/pkg/diag"
)

// Frame contains information of the current running function, aknin to a call
// frame in native CPU execution. A Frame is only modified during and very
// shortly after creation; new Frame's are "forked" when needed.
type Frame struct {
	*Evaler
	srcMeta *Source

	local, up Ns
	ports     []*Port

	begin, end int
	traceback  *stackTrace

	background bool
}

// NewTopFrame creates a top-level Frame.
//
// TODO(xiaq): This should be a method on the Evaler.
func NewTopFrame(ev *Evaler, src *Source, ports []*Port) *Frame {
	return &Frame{
		ev, src,
		ev.Global, make(Ns),
		ports,
		0, len(src.Code), nil, false,
	}
}

// SetLocal changes the local scope of the Frame.
func (fm *Frame) SetLocal(ns Ns) {
	fm.local = ns
}

// Close releases resources allocated for this frame. It always returns a nil
// error. It may be called only once.
func (fm *Frame) Close() error {
	for _, port := range fm.ports {
		port.Close()
	}
	return nil
}

// InputChan returns a channel from which input can be read.
func (fm *Frame) InputChan() chan interface{} {
	return fm.ports[0].Chan
}

// InputFile returns a file from which input can be read.
func (fm *Frame) InputFile() *os.File {
	return fm.ports[0].File
}

// OutputChan returns a channel onto which output can be written.
func (fm *Frame) OutputChan() chan<- interface{} {
	return fm.ports[1].Chan
}

// OutputFile returns a file onto which output can be written.
func (fm *Frame) OutputFile() *os.File {
	return fm.ports[1].File
}

// IterateInputs calls the passed function for each input element.
func (fm *Frame) IterateInputs(f func(interface{})) {
	var w sync.WaitGroup
	inputs := make(chan interface{})

	w.Add(2)
	go func() {
		linesToChan(fm.ports[0].File, inputs)
		w.Done()
	}()
	go func() {
		for v := range fm.ports[0].Chan {
			inputs <- v
		}
		w.Done()
	}()
	go func() {
		w.Wait()
		close(inputs)
	}()

	for v := range inputs {
		f(v)
	}
}

func linesToChan(r io.Reader, ch chan<- interface{}) {
	filein := bufio.NewReader(r)
	for {
		line, err := filein.ReadString('\n')
		if line != "" {
			ch <- strings.TrimSuffix(line, "\n")
		}
		if err != nil {
			if err != io.EOF {
				logger.Println("error on reading:", err)
			}
			break
		}
	}
}

// fork returns a modified copy of ec. The ports are forked, and the name is
// changed to the given value. Other fields are copied shallowly.
func (fm *Frame) fork(name string) *Frame {
	newPorts := make([]*Port, len(fm.ports))
	for i, p := range fm.ports {
		if p != nil {
			newPorts[i] = p.Fork()
		}
	}
	return &Frame{
		fm.Evaler, fm.srcMeta,
		fm.local, fm.up,
		newPorts,
		fm.begin, fm.end, fm.traceback, fm.background,
	}
}

// Eval evaluates an Op. It is like eval except that it sets fm.srcMeta
// temporarily to op.src during the evaluation.
func (fm *Frame) Eval(op Op) error {
	oldSrc := fm.srcMeta
	fm.srcMeta = op.Src
	defer func() {
		fm.srcMeta = oldSrc
	}()
	return fm.eval(op.Inner)
}

// eval evaluates an effectOp. It does so in a protected environment so that
// exceptions thrown are wrapped in an Error.
func (fm *Frame) eval(op effectOp) (err error) {
	e := op.exec(fm)
	if e != nil {
		if exc, ok := e.(*Exception); ok {
			return exc
		}
		return fm.makeException(e)
	}
	return nil
}

// Call calls a function with the given arguments and options. It does so in a
// protected environment so that exceptions thrown are wrapped in an Error.
func (fm *Frame) Call(f Callable, args []interface{}, opts map[string]interface{}) (err error) {
	e := f.Call(fm, args, opts)
	if e != nil {
		if exc, ok := e.(*Exception); ok {
			return exc
		}
		return fm.makeException(e)
	}
	return nil
}

// CaptureOutput calls a function with the given arguments and options,
// capturing and returning the output. It does so in a protected environment so
// that exceptions thrown are wrapped in an Error.
func (fm *Frame) CaptureOutput(fn Callable, args []interface{}, opts map[string]interface{}) (vs []interface{}, err error) {
	// XXX There is no source.
	opFunc := func(f *Frame) error {
		return fn.Call(f, args, opts)
	}
	return pcaptureOutput(fm, effectOp{funcOp(opFunc), -1, -1})
}

// CallWithOutputCallback calls a function with the given arguments and options,
// feeding the outputs to the given callbacks. It does so in a protected
// environment so that exceptions thrown are wrapped in an Error.
func (fm *Frame) CallWithOutputCallback(fn Callable, args []interface{}, opts map[string]interface{}, valuesCb func(<-chan interface{}), bytesCb func(*os.File)) error {
	// XXX There is no source.
	opFunc := func(f *Frame) error {
		return fn.Call(f, args, opts)
	}
	return pcaptureOutputInner(fm, effectOp{funcOp(opFunc), -1, -1}, valuesCb, bytesCb)
}

// ExecWithOutputCallback executes an Op, feeding the outputs to the given
// callbacks.
func (fm *Frame) ExecWithOutputCallback(op Op, valuesCb func(<-chan interface{}), bytesCb func(*os.File)) error {
	return pcaptureOutputInner(fm, op.Inner, valuesCb, bytesCb)
}

// makeException turns an error into an Exception by adding traceback.
func (fm *Frame) makeException(e error) *Exception {
	return &Exception{e, fm.addTraceback()}
}

func (fm *Frame) addTraceback() *stackTrace {
	return &stackTrace{
		entry: diag.NewContext(
			fm.srcMeta.Name, fm.srcMeta.Code, fm.begin, fm.end),
		next: fm.traceback,
	}
}

// Amends the being and end of the current frame and returns the result of
// fmt.Errorf.
func (fm *Frame) errorpf(begin, end int, format string, args ...interface{}) error {
	fm.begin, fm.end = begin, end
	return fmt.Errorf(format, args...)
}
<commit_msg>pkg/eval: Factor all exception logic to (*Frame).makeException.<commit_after>package eval

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/elves/elvish/pkg/diag"
)

// Frame contains information of the current running function, aknin to a call
// frame in native CPU execution. A Frame is only modified during and very
// shortly after creation; new Frame's are "forked" when needed.
type Frame struct {
	*Evaler
	srcMeta *Source

	local, up Ns
	ports     []*Port

	begin, end int
	traceback  *stackTrace

	background bool
}

// NewTopFrame creates a top-level Frame.
//
// TODO(xiaq): This should be a method on the Evaler.
func NewTopFrame(ev *Evaler, src *Source, ports []*Port) *Frame {
	return &Frame{
		ev, src,
		ev.Global, make(Ns),
		ports,
		0, len(src.Code), nil, false,
	}
}

// SetLocal changes the local scope of the Frame.
func (fm *Frame) SetLocal(ns Ns) {
	fm.local = ns
}

// Close releases resources allocated for this frame. It always returns a nil
// error. It may be called only once.
func (fm *Frame) Close() error {
	for _, port := range fm.ports {
		port.Close()
	}
	return nil
}

// InputChan returns a channel from which input can be read.
func (fm *Frame) InputChan() chan interface{} {
	return fm.ports[0].Chan
}

// InputFile returns a file from which input can be read.
func (fm *Frame) InputFile() *os.File {
	return fm.ports[0].File
}

// OutputChan returns a channel onto which output can be written.
func (fm *Frame) OutputChan() chan<- interface{} {
	return fm.ports[1].Chan
}

// OutputFile returns a file onto which output can be written.
func (fm *Frame) OutputFile() *os.File {
	return fm.ports[1].File
}

// IterateInputs calls the passed function for each input element.
func (fm *Frame) IterateInputs(f func(interface{})) {
	var w sync.WaitGroup
	inputs := make(chan interface{})

	w.Add(2)
	go func() {
		linesToChan(fm.ports[0].File, inputs)
		w.Done()
	}()
	go func() {
		for v := range fm.ports[0].Chan {
			inputs <- v
		}
		w.Done()
	}()
	go func() {
		w.Wait()
		close(inputs)
	}()

	for v := range inputs {
		f(v)
	}
}

func linesToChan(r io.Reader, ch chan<- interface{}) {
	filein := bufio.NewReader(r)
	for {
		line, err := filein.ReadString('\n')
		if line != "" {
			ch <- strings.TrimSuffix(line, "\n")
		}
		if err != nil {
			if err != io.EOF {
				logger.Println("error on reading:", err)
			}
			break
		}
	}
}

// fork returns a modified copy of ec. The ports are forked, and the name is
// changed to the given value. Other fields are copied shallowly.
func (fm *Frame) fork(name string) *Frame {
	newPorts := make([]*Port, len(fm.ports))
	for i, p := range fm.ports {
		if p != nil {
			newPorts[i] = p.Fork()
		}
	}
	return &Frame{
		fm.Evaler, fm.srcMeta,
		fm.local, fm.up,
		newPorts,
		fm.begin, fm.end, fm.traceback, fm.background,
	}
}

// Eval evaluates an Op. It is like eval except that it sets fm.srcMeta
// temporarily to op.src during the evaluation.
func (fm *Frame) Eval(op Op) error {
	oldSrc := fm.srcMeta
	fm.srcMeta = op.Src
	defer func() {
		fm.srcMeta = oldSrc
	}()
	return fm.eval(op.Inner)
}

// eval evaluates an effectOp. It does so in a protected environment so that
// exceptions thrown are wrapped in an Error.
func (fm *Frame) eval(op effectOp) (err error) {
	e := op.exec(fm)
	return fm.makeException(e)
}

// Call calls a function with the given arguments and options. It does so in a
// protected environment so that exceptions thrown are wrapped in an Error.
func (fm *Frame) Call(f Callable, args []interface{}, opts map[string]interface{}) (err error) {
	e := f.Call(fm, args, opts)
	return fm.makeException(e)
}

// CaptureOutput calls a function with the given arguments and options,
// capturing and returning the output. It does so in a protected environment so
// that exceptions thrown are wrapped in an Error.
func (fm *Frame) CaptureOutput(fn Callable, args []interface{}, opts map[string]interface{}) (vs []interface{}, err error) {
	// XXX There is no source.
	opFunc := func(f *Frame) error {
		return fn.Call(f, args, opts)
	}
	return pcaptureOutput(fm, effectOp{funcOp(opFunc), -1, -1})
}

// CallWithOutputCallback calls a function with the given arguments and options,
// feeding the outputs to the given callbacks. It does so in a protected
// environment so that exceptions thrown are wrapped in an Error.
func (fm *Frame) CallWithOutputCallback(fn Callable, args []interface{}, opts map[string]interface{}, valuesCb func(<-chan interface{}), bytesCb func(*os.File)) error {
	// XXX There is no source.
	opFunc := func(f *Frame) error {
		return fn.Call(f, args, opts)
	}
	return pcaptureOutputInner(fm, effectOp{funcOp(opFunc), -1, -1}, valuesCb, bytesCb)
}

// ExecWithOutputCallback executes an Op, feeding the outputs to the given
// callbacks.
func (fm *Frame) ExecWithOutputCallback(op Op, valuesCb func(<-chan interface{}), bytesCb func(*os.File)) error {
	return pcaptureOutputInner(fm, op.Inner, valuesCb, bytesCb)
}

// makeException turns an error into an Exception by adding traceback. If e is
// nil or already an *Exception, it is returned as is.
func (fm *Frame) makeException(e error) error {
	switch e := e.(type) {
	case nil:
		return nil
	case *Exception:
		return e
	default:
		return &Exception{e, fm.addTraceback()}
	}
}

func (fm *Frame) addTraceback() *stackTrace {
	return &stackTrace{
		entry: diag.NewContext(
			fm.srcMeta.Name, fm.srcMeta.Code, fm.begin, fm.end),
		next: fm.traceback,
	}
}

// Amends the being and end of the current frame and returns the result of
// fmt.Errorf.
func (fm *Frame) errorpf(begin, end int, format string, args ...interface{}) error {
	fm.begin, fm.end = begin, end
	return fmt.Errorf(format, args...)
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google 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 index

import (
	"bytes"
	"fmt"
	"strings"
)

// requiredSchemaVersion is incremented every time
// an index key type is added, changed, or removed.
const requiredSchemaVersion = 3

// type of key returns the identifier in k before the first ":" or "|".
// (Originally we packed keys by hand and there are a mix of styles)
func typeOfKey(k string) string {
	c := strings.Index(k, ":")
	p := strings.Index(k, "|")
	if c < 0 && p < 0 {
		return ""
	}
	if c < 0 {
		return k[:p]
	}
	if p < 0 {
		return k[:c]
	}
	min := c
	if p < min {
		min = p
	}
	return k[:min]
}

type keyType struct {
	name     string
	keyParts []part
	valParts []part
}

func (k *keyType) Prefix(args ...interface{}) string {
	return k.build(true, true, k.keyParts, args...)
}

func (k *keyType) Key(args ...interface{}) string {
	return k.build(false, true, k.keyParts, args...)
}

func (k *keyType) Val(args ...interface{}) string {
	return k.build(false, false, k.valParts, args...)
}

func (k *keyType) build(isPrefix, isKey bool, parts []part, args ...interface{}) string {
	var buf bytes.Buffer
	if isKey {
		buf.WriteString(k.name)
	}
	if !isPrefix && len(args) != len(parts) {
		panic("wrong number of arguments")
	}
	if len(args) > len(parts) {
		panic("too many arguments")
	}
	for i, arg := range args {
		if isKey || i > 0 {
			buf.WriteString("|")
		}
		asStr := func() string {
			s, ok := arg.(string)
			if !ok {
				s = arg.(fmt.Stringer).String()
			}
			return s
		}
		switch parts[i].typ {
		case typeIntStr:
			switch arg.(type) {
			case int, int64, uint64:
				buf.WriteString(fmt.Sprintf("%d", arg))
			default:
				panic("bogus int type")
			}
		case typeStr:
			buf.WriteString(urle(asStr()))
		case typeRawStr:
			buf.WriteString(asStr())
		case typeReverseTime:
			s := asStr()
			const example = "2011-01-23T05:23:12"
			if len(s) < len(example) || s[4] != '-' && s[10] != 'T' {
				panic("doesn't look like a time: " + s)
			}
			buf.WriteString(reverseTimeString(s))
		default:
			if s, ok := arg.(string); ok {
				buf.WriteString(s)
			} else {
				buf.WriteString(arg.(fmt.Stringer).String())
			}
		}
	}
	if isPrefix {
		buf.WriteString("|")
	}
	return buf.String()
}

type part struct {
	name string
	typ  partType
}

type partType int

const (
	typeKeyId partType = iota // PGP key id
	typeTime
	typeReverseTime // time prepended with "rt" + each numeric digit reversed from '9'
	typeBlobRef
	typeStr    // URL-escaped
	typeIntStr // integer as string
	typeRawStr // not URL-escaped
)

var (
	// keySchemaVersion indexes the index schema version.
	keySchemaVersion = &keyType{
		"schemaversion",
		nil,
		[]part{
			{"version", typeIntStr},
		},
	}

	// keyPermanodeClaim indexes when a permanode is modified (or deleted) by a claim.
	// It ties the affected permanode to the date of the modification, the responsible
	// claim, and the nature of the modification.
	keyPermanodeClaim = &keyType{
		"claim",
		[]part{
			{"permanode", typeBlobRef}, // modified permanode
			{"signer", typeKeyId},
			{"claimDate", typeTime},
			{"claim", typeBlobRef},
		},
		[]part{
			{"claimType", typeStr},
			{"attr", typeStr},
			{"value", typeStr},
			// And the signerRef, which seems redundant
			// with the signer keyId in the jey, but the
			// Claim struct needs this, and there's 1:m
			// for keyId:blobRef, so:
			{"signerRef", typeBlobRef},
		},
	}

	keyRecentPermanode = &keyType{
		"recpn",
		[]part{
			{"owner", typeKeyId},
			{"modtime", typeReverseTime},
			{"claim", typeBlobRef},
		},
		nil,
	}

	keyPathBackward = &keyType{
		"signertargetpath",
		[]part{
			{"signer", typeKeyId},
			{"target", typeBlobRef},
			{"claim", typeBlobRef}, // for key uniqueness
		},
		[]part{
			{"claimDate", typeTime},
			{"base", typeBlobRef},
			{"active", typeStr}, // 'Y', or 'N' for deleted
			{"suffix", typeStr},
		},
	}

	keyPathForward = &keyType{
		"path",
		[]part{
			{"signer", typeKeyId},
			{"base", typeBlobRef},
			{"suffix", typeStr},
			{"claimDate", typeReverseTime},
			{"claim", typeBlobRef}, // for key uniqueness
		},
		[]part{
			{"active", typeStr}, // 'Y', or 'N' for deleted
			{"target", typeBlobRef},
		},
	}

	keyWholeToFileRef = &keyType{
		"wholetofile",
		[]part{
			{"whole", typeBlobRef},
			{"schema", typeBlobRef}, // for key uniqueness
		},
		[]part{
			{"1", typeStr},
		},
	}

	keyFileInfo = &keyType{
		"fileinfo",
		[]part{
			{"file", typeBlobRef},
		},
		[]part{
			{"size", typeIntStr},
			{"filename", typeStr},
			{"mimetype", typeStr},
		},
	}

	keyFileTimes = &keyType{
		"filetimes",
		[]part{
			{"file", typeBlobRef},
		},
		[]part{
			// 0, 1, or 2 comma-separated types.Time3339
			// strings for creation/mod times. Oldest,
			// then newest. See FileInfo docs.
			{"time3339s", typeStr},
		},
	}

	keySignerAttrValue = &keyType{
		"signerattrvalue",
		[]part{
			{"signer", typeKeyId},
			{"attr", typeStr},
			{"value", typeStr},
			{"claimdate", typeReverseTime},
			{"claimref", typeBlobRef},
		},
		[]part{
			{"permanode", typeBlobRef},
		},
	}

	// keyDeleted indexes a claim that deletes an entity. It ties the deleted
	// entity to the date it was deleted, and to the deleter claim.
	keyDeleted = &keyType{
		"deleted",
		[]part{
			{"deleted", typeBlobRef}, // the deleted entity (a permanode or another claim)
			{"claimdate", typeReverseTime},
			{"deleter", typeBlobRef}, // the deleter claim blobref
		},
		nil,
	}

	// Given a blobref (permanode or static file or directory), provide a mapping
	// to potential parents (they may no longer be parents, in the case of permanodes).
	// In the case of permanodes, camliMember or camliContent constitutes a forward
	// edge.  In the case of static directories, the forward path is dir->static set->file,
	// and that's what's indexed here, inverted.
	keyEdgeBackward = &keyType{
		"edgeback",
		[]part{
			{"child", typeBlobRef},  // the edge target; thing we want to find parent(s) of
			{"parent", typeBlobRef}, // the parent / edge source (e.g. permanode blobref)
			// the blobref is the blob establishing the relationship
			// (for a permanode: the claim; for static: often same as parent)
			{"blobref", typeBlobRef},
		},
		[]part{
			{"parenttype", typeStr}, // either "permanode" or the camliType ("file", "static-set", etc)
			{"name", typeStr},       // the name, if static.
		},
	}

	// Width and height after any EXIF rotation.
	keyImageSize = &keyType{
		"imagesize",
		[]part{
			{"fileref", typeBlobRef}, // blobref of "file" schema blob
		},
		[]part{
			{"width", typeStr},
			{"height", typeStr},
		},
	}

	// child of a directory
	keyStaticDirChild = &keyType{
		"dirchild",
		[]part{
			{"dirref", typeBlobRef}, // blobref of "directory" schema blob
			{"child", typeStr},      // blobref of the child
		},
		[]part{
			{"1", typeStr},
		},
	}

	// Audio attributes (e.g., ID3 tags). Uses generic terms like
	// "artist", "title", "album", etc.
	keyAudioTag = &keyType{
		"audiotag",
		[]part{
			{"tag", typeStr},
			{"value", typeStr},
			{"wholeRef", typeBlobRef}, // wholeRef for song
		},
		nil,
	}

	// EXIF tags
	keyEXIFTag = &keyType{
		"exiftag",
		[]part{
			{"wholeRef", typeBlobRef}, // of entire file, not fileref
			{"tag", typeStr},          // uint16 tag number as hex: xxxx
		},
		[]part{
			{"type", typeStr},    // "int", "rat", "float", "string"
			{"n", typeIntStr},    // n components of type
			{"vals", typeRawStr}, // pipe-separated; rats are n/d. strings are URL-escaped.
		},
	}

	// Redundant version of keyEXIFTag. TODO: maybe get rid of this.
	// Easier to process as one row instead of 4, though.
	keyEXIFGPS = &keyType{
		"exifgps",
		[]part{
			{"wholeRef", typeBlobRef}, // of entire file, not fileref
		},
		[]part{
			{"lat", typeStr},
			{"long", typeStr},
		},
	}
)

func containsUnsafeRawStrByte(s string) bool {
	for _, r := range s {
		if r >= 'z' || r < ' ' {
			// pipe ('|) and non-ASCII are above 'z'.
			return true
		}
		if r == '%' || r == '+' {
			// Could be interpretted as URL-encoded
			return true
		}
	}
	return false
}
<commit_msg>index: bump schema version for EXIF changes<commit_after>/*
Copyright 2011 Google 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 index

import (
	"bytes"
	"fmt"
	"strings"
)

// requiredSchemaVersion is incremented every time
// an index key type is added, changed, or removed.
// Version 4: EXIF tags + GPS
const requiredSchemaVersion = 4

// type of key returns the identifier in k before the first ":" or "|".
// (Originally we packed keys by hand and there are a mix of styles)
func typeOfKey(k string) string {
	c := strings.Index(k, ":")
	p := strings.Index(k, "|")
	if c < 0 && p < 0 {
		return ""
	}
	if c < 0 {
		return k[:p]
	}
	if p < 0 {
		return k[:c]
	}
	min := c
	if p < min {
		min = p
	}
	return k[:min]
}

type keyType struct {
	name     string
	keyParts []part
	valParts []part
}

func (k *keyType) Prefix(args ...interface{}) string {
	return k.build(true, true, k.keyParts, args...)
}

func (k *keyType) Key(args ...interface{}) string {
	return k.build(false, true, k.keyParts, args...)
}

func (k *keyType) Val(args ...interface{}) string {
	return k.build(false, false, k.valParts, args...)
}

func (k *keyType) build(isPrefix, isKey bool, parts []part, args ...interface{}) string {
	var buf bytes.Buffer
	if isKey {
		buf.WriteString(k.name)
	}
	if !isPrefix && len(args) != len(parts) {
		panic("wrong number of arguments")
	}
	if len(args) > len(parts) {
		panic("too many arguments")
	}
	for i, arg := range args {
		if isKey || i > 0 {
			buf.WriteString("|")
		}
		asStr := func() string {
			s, ok := arg.(string)
			if !ok {
				s = arg.(fmt.Stringer).String()
			}
			return s
		}
		switch parts[i].typ {
		case typeIntStr:
			switch arg.(type) {
			case int, int64, uint64:
				buf.WriteString(fmt.Sprintf("%d", arg))
			default:
				panic("bogus int type")
			}
		case typeStr:
			buf.WriteString(urle(asStr()))
		case typeRawStr:
			buf.WriteString(asStr())
		case typeReverseTime:
			s := asStr()
			const example = "2011-01-23T05:23:12"
			if len(s) < len(example) || s[4] != '-' && s[10] != 'T' {
				panic("doesn't look like a time: " + s)
			}
			buf.WriteString(reverseTimeString(s))
		default:
			if s, ok := arg.(string); ok {
				buf.WriteString(s)
			} else {
				buf.WriteString(arg.(fmt.Stringer).String())
			}
		}
	}
	if isPrefix {
		buf.WriteString("|")
	}
	return buf.String()
}

type part struct {
	name string
	typ  partType
}

type partType int

const (
	typeKeyId partType = iota // PGP key id
	typeTime
	typeReverseTime // time prepended with "rt" + each numeric digit reversed from '9'
	typeBlobRef
	typeStr    // URL-escaped
	typeIntStr // integer as string
	typeRawStr // not URL-escaped
)

var (
	// keySchemaVersion indexes the index schema version.
	keySchemaVersion = &keyType{
		"schemaversion",
		nil,
		[]part{
			{"version", typeIntStr},
		},
	}

	// keyPermanodeClaim indexes when a permanode is modified (or deleted) by a claim.
	// It ties the affected permanode to the date of the modification, the responsible
	// claim, and the nature of the modification.
	keyPermanodeClaim = &keyType{
		"claim",
		[]part{
			{"permanode", typeBlobRef}, // modified permanode
			{"signer", typeKeyId},
			{"claimDate", typeTime},
			{"claim", typeBlobRef},
		},
		[]part{
			{"claimType", typeStr},
			{"attr", typeStr},
			{"value", typeStr},
			// And the signerRef, which seems redundant
			// with the signer keyId in the jey, but the
			// Claim struct needs this, and there's 1:m
			// for keyId:blobRef, so:
			{"signerRef", typeBlobRef},
		},
	}

	keyRecentPermanode = &keyType{
		"recpn",
		[]part{
			{"owner", typeKeyId},
			{"modtime", typeReverseTime},
			{"claim", typeBlobRef},
		},
		nil,
	}

	keyPathBackward = &keyType{
		"signertargetpath",
		[]part{
			{"signer", typeKeyId},
			{"target", typeBlobRef},
			{"claim", typeBlobRef}, // for key uniqueness
		},
		[]part{
			{"claimDate", typeTime},
			{"base", typeBlobRef},
			{"active", typeStr}, // 'Y', or 'N' for deleted
			{"suffix", typeStr},
		},
	}

	keyPathForward = &keyType{
		"path",
		[]part{
			{"signer", typeKeyId},
			{"base", typeBlobRef},
			{"suffix", typeStr},
			{"claimDate", typeReverseTime},
			{"claim", typeBlobRef}, // for key uniqueness
		},
		[]part{
			{"active", typeStr}, // 'Y', or 'N' for deleted
			{"target", typeBlobRef},
		},
	}

	keyWholeToFileRef = &keyType{
		"wholetofile",
		[]part{
			{"whole", typeBlobRef},
			{"schema", typeBlobRef}, // for key uniqueness
		},
		[]part{
			{"1", typeStr},
		},
	}

	keyFileInfo = &keyType{
		"fileinfo",
		[]part{
			{"file", typeBlobRef},
		},
		[]part{
			{"size", typeIntStr},
			{"filename", typeStr},
			{"mimetype", typeStr},
		},
	}

	keyFileTimes = &keyType{
		"filetimes",
		[]part{
			{"file", typeBlobRef},
		},
		[]part{
			// 0, 1, or 2 comma-separated types.Time3339
			// strings for creation/mod times. Oldest,
			// then newest. See FileInfo docs.
			{"time3339s", typeStr},
		},
	}

	keySignerAttrValue = &keyType{
		"signerattrvalue",
		[]part{
			{"signer", typeKeyId},
			{"attr", typeStr},
			{"value", typeStr},
			{"claimdate", typeReverseTime},
			{"claimref", typeBlobRef},
		},
		[]part{
			{"permanode", typeBlobRef},
		},
	}

	// keyDeleted indexes a claim that deletes an entity. It ties the deleted
	// entity to the date it was deleted, and to the deleter claim.
	keyDeleted = &keyType{
		"deleted",
		[]part{
			{"deleted", typeBlobRef}, // the deleted entity (a permanode or another claim)
			{"claimdate", typeReverseTime},
			{"deleter", typeBlobRef}, // the deleter claim blobref
		},
		nil,
	}

	// Given a blobref (permanode or static file or directory), provide a mapping
	// to potential parents (they may no longer be parents, in the case of permanodes).
	// In the case of permanodes, camliMember or camliContent constitutes a forward
	// edge.  In the case of static directories, the forward path is dir->static set->file,
	// and that's what's indexed here, inverted.
	keyEdgeBackward = &keyType{
		"edgeback",
		[]part{
			{"child", typeBlobRef},  // the edge target; thing we want to find parent(s) of
			{"parent", typeBlobRef}, // the parent / edge source (e.g. permanode blobref)
			// the blobref is the blob establishing the relationship
			// (for a permanode: the claim; for static: often same as parent)
			{"blobref", typeBlobRef},
		},
		[]part{
			{"parenttype", typeStr}, // either "permanode" or the camliType ("file", "static-set", etc)
			{"name", typeStr},       // the name, if static.
		},
	}

	// Width and height after any EXIF rotation.
	keyImageSize = &keyType{
		"imagesize",
		[]part{
			{"fileref", typeBlobRef}, // blobref of "file" schema blob
		},
		[]part{
			{"width", typeStr},
			{"height", typeStr},
		},
	}

	// child of a directory
	keyStaticDirChild = &keyType{
		"dirchild",
		[]part{
			{"dirref", typeBlobRef}, // blobref of "directory" schema blob
			{"child", typeStr},      // blobref of the child
		},
		[]part{
			{"1", typeStr},
		},
	}

	// Audio attributes (e.g., ID3 tags). Uses generic terms like
	// "artist", "title", "album", etc.
	keyAudioTag = &keyType{
		"audiotag",
		[]part{
			{"tag", typeStr},
			{"value", typeStr},
			{"wholeRef", typeBlobRef}, // wholeRef for song
		},
		nil,
	}

	// EXIF tags
	keyEXIFTag = &keyType{
		"exiftag",
		[]part{
			{"wholeRef", typeBlobRef}, // of entire file, not fileref
			{"tag", typeStr},          // uint16 tag number as hex: xxxx
		},
		[]part{
			{"type", typeStr},    // "int", "rat", "float", "string"
			{"n", typeIntStr},    // n components of type
			{"vals", typeRawStr}, // pipe-separated; rats are n/d. strings are URL-escaped.
		},
	}

	// Redundant version of keyEXIFTag. TODO: maybe get rid of this.
	// Easier to process as one row instead of 4, though.
	keyEXIFGPS = &keyType{
		"exifgps",
		[]part{
			{"wholeRef", typeBlobRef}, // of entire file, not fileref
		},
		[]part{
			{"lat", typeStr},
			{"long", typeStr},
		},
	}
)

func containsUnsafeRawStrByte(s string) bool {
	for _, r := range s {
		if r >= 'z' || r < ' ' {
			// pipe ('|) and non-ASCII are above 'z'.
			return true
		}
		if r == '%' || r == '+' {
			// Could be interpretted as URL-encoded
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Package errors generates the common errors for the modules
package errors

import (
	"fmt"
	"log"
	"strings"

	"github.com/cihangir/gene/generators/common"
	"github.com/kr/pretty"
)

type Generator struct{}

func pathfunc(data *common.TemplateData) string {
	log.Printf("data.Settings.Ge.(string) %# v", pretty.Formatter(data.Settings.Get("fullPathPrefix").(string)))
	return fmt.Sprintf(
		"%s/%s.go",
		data.Settings.Get("fullPathPrefix").(string),
		strings.ToLower(data.Schema.Title),
	)
}

// Generate generates and writes the errors of the schema
func (g *Generator) Generate(req *common.Req, res *common.Res) error {
	o := &common.Op{
		Name:     "errors",
		Template: ErrorsTemplate,
		PathFunc: pathfunc,
		Clear:    true,
	}

	return common.Proces(o, req, res)
}
<commit_msg>gene: remove unnecessary log statements<commit_after>// Package errors generates the common errors for the modules
package errors

import (
	"fmt"
	"strings"

	"github.com/cihangir/gene/generators/common"
)

type Generator struct{}

func pathfunc(data *common.TemplateData) string {
	return fmt.Sprintf(
		"%s/%s.go",
		data.Settings.Get("fullPathPrefix").(string),
		strings.ToLower(data.Schema.Title),
	)
}

// Generate generates and writes the errors of the schema
func (g *Generator) Generate(req *common.Req, res *common.Res) error {
	o := &common.Op{
		Name:     "errors",
		Template: ErrorsTemplate,
		PathFunc: pathfunc,
		Clear:    true,
	}

	return common.Proces(o, req, res)
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

import (
	"errors"
	"fmt"

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

type PaperProvisionEngine struct {
	libkb.Contextified
	Username   string
	DeviceName string
	PaperKey   string
	result     error
	lks        *libkb.LKSec
	User       *libkb.User
}

func NewPaperProvisionEngine(g *libkb.GlobalContext, username, deviceName, paperKey string) *PaperProvisionEngine {
	return &PaperProvisionEngine{
		Contextified: libkb.NewContextified(g),
		Username:     username,
		DeviceName:   deviceName,
		PaperKey:     paperKey,
	}
}

func (e *PaperProvisionEngine) Name() string {
	return "PaperProvision"
}

func (e *PaperProvisionEngine) Prereqs() Prereqs {
	return Prereqs{}
}

func (e *PaperProvisionEngine) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{
		libkb.ProvisionUIKind,
		libkb.LogUIKind,
		libkb.SecretUIKind,
		libkb.LoginUIKind,
	}
}

func (e *PaperProvisionEngine) Run(ctx *Context) (err error) {
	e.G().Log.Debug("+ PaperProvisionEngine Run")

	defer e.G().Trace("PaperProvisionEngine#Run", func() error { return err })()

	// clear out any existing session:
	e.G().Logout()

	// transaction around config file
	tx, err := e.G().Env.GetConfigWriter().BeginTransaction()
	if err != nil {
		return err
	}

	// From this point on, if there's an error, we abort the
	// transaction.
	defer func() {
		if tx != nil {
			tx.Abort()
		}
	}()

	// run the LoginLoadUser sub-engine to load a user
	ueng := newLoginLoadUser(e.G(), e.Username)
	if err = RunEngine(ueng, ctx); err != nil {
		return err
	}

	// make sure the user isn't already provisioned (can
	// get here if usernameOrEmail is an email address
	// for an already provisioned on this device user).
	if ueng.User().HasCurrentDeviceInCurrentInstall() {
		return libkb.DeviceAlreadyProvisionedError{}
	}
	e.User = ueng.User()

	// Transform the paper key phrase into a key pair
	bkarg := &PaperKeyGenArg{
		Passphrase: libkb.PaperKeyPhrase(e.PaperKey),
		SkipPush:   true,
	}
	bkeng := NewPaperKeyGen(bkarg, e.G())
	if err := RunEngine(bkeng, ctx); err != nil {
		return err
	}

	kp := &keypair{sigKey: bkeng.SigKey(), encKey: bkeng.EncKey()}

	// Make sure the key matches the logged in user
	// use the KID to find the uid
	uid, err := e.uidByKID(kp.sigKey.GetKID())
	if err != nil {
		return err
	}

	if uid.NotEqual(e.User.GetUID()) {
		e.G().Log.Debug("paper key entered was for a different user")
		return fmt.Errorf("paper key valid, but for %s, not %s", uid, e.User.GetUID())
	}

	// Make new device keys and sign them with this paper key
	err = e.paper(ctx, kp)
	if err != nil {
		return err
	}

	// commit the config changes
	if err := tx.Commit(); err != nil {
		return err
	}
	if err := e.G().LoginState().Account(func(a *libkb.Account) {
		a.SetUnlockedPaperKey(kp.sigKey, kp.encKey)
	}, "UnlockedPaperKey"); err != nil {
		return err
	}

	// Zero out the TX so that we don't abort it in the defer()
	// exit.
	tx = nil

	e.sendNotification()
	return nil

}

// Copied from login_provision.go
func (e *PaperProvisionEngine) uidByKID(kid keybase1.KID) (keybase1.UID, error) {
	var nilUID keybase1.UID
	arg := libkb.APIArg{
		Endpoint:     "key/owner",
		NeedSession:  false,
		Contextified: libkb.NewContextified(e.G()),
		Args:         libkb.HTTPArgs{"kid": libkb.S{Val: kid.String()}},
	}
	res, err := e.G().API.Get(arg)
	if err != nil {
		return nilUID, err
	}
	suid, err := res.Body.AtPath("uid").GetString()
	if err != nil {
		return nilUID, err
	}
	return keybase1.UIDFromString(suid)
}

// copied more or less from loginProvision.paper()
func (e *PaperProvisionEngine) paper(ctx *Context, kp *keypair) error {
	// After obtaining login session, this will be called before the login state is released.
	// It signs this new device with the paper key.
	var afterLogin = func(lctx libkb.LoginContext) error {
		ctx.LoginContext = lctx

		// need lksec to store device keys locally
		if err := e.fetchLKS(ctx, kp.encKey); err != nil {
			return err
		}

		if err := e.makeDeviceKeysWithSigner(ctx, kp.sigKey); err != nil {
			return err
		}
		if err := lctx.LocalSession().SetDeviceProvisioned(e.G().Env.GetDeviceID()); err != nil {
			// not a fatal error, session will stay in memory
			e.G().Log.Warning("error saving session file: %s", err)
		}
		return nil
	}

	// need a session to continue to provision, login with paper sigKey
	return e.G().LoginState().LoginWithKey(ctx.LoginContext, e.User, kp.sigKey, afterLogin)
}

func (e *PaperProvisionEngine) sendNotification() {
	e.G().NotifyRouter.HandleLogin(string(e.G().Env.GetUsername()))
}

func (e *PaperProvisionEngine) SubConsumers() []libkb.UIConsumer {
	return []libkb.UIConsumer{
		&loginLoadUser{},
	}
}

func (e *PaperProvisionEngine) Result() error {
	return e.result
}

// copied from loginProvision
func (e *PaperProvisionEngine) fetchLKS(ctx *Context, encKey libkb.GenericKey) error {
	gen, clientLKS, err := fetchLKS(ctx, e.G(), encKey)
	if err != nil {
		return err
	}
	e.lks = libkb.NewLKSecWithClientHalf(clientLKS, gen, e.User.GetUID(), e.G())
	return nil
}

// copied from loginProvision
// makeDeviceKeysWithSigner creates device keys given a signing
// key.
func (e *PaperProvisionEngine) makeDeviceKeysWithSigner(ctx *Context, signer libkb.GenericKey) error {
	args, err := e.makeDeviceWrapArgs(ctx)
	if err != nil {
		return err
	}
	args.Signer = signer
	args.IsEldest = false // just to be explicit
	args.EldestKID = e.User.GetEldestKID()

	return e.makeDeviceKeys(ctx, args)
}

// copied from loginProvision
// makeDeviceWrapArgs creates a base set of args for DeviceWrap.
// It ensures that LKSec is created.  It also gets a new device
// name for this device.
func (e *PaperProvisionEngine) makeDeviceWrapArgs(ctx *Context) (*DeviceWrapArgs, error) {
	if err := e.ensureLKSec(ctx); err != nil {
		return nil, err
	}

	return &DeviceWrapArgs{
		Me:         e.User,
		DeviceName: e.DeviceName,
		DeviceType: "desktop",
		Lks:        e.lks,
	}, nil
}

// copied from loginProvision
// makeDeviceKeys uses DeviceWrap to generate device keys.
func (e *PaperProvisionEngine) makeDeviceKeys(ctx *Context, args *DeviceWrapArgs) error {
	eng := NewDeviceWrap(args, e.G())
	if err := RunEngine(eng, ctx); err != nil {
		return err
	}

	return nil
}

// copied from loginProvision
// ensureLKSec ensures we have LKSec for saving device keys.
func (e *PaperProvisionEngine) ensureLKSec(ctx *Context) error {
	if e.lks != nil {
		return nil
	}

	pps, err := e.ppStream(ctx)
	if err != nil {
		return err
	}

	e.lks = libkb.NewLKSec(pps, e.User.GetUID(), e.G())
	return nil
}

// copied from loginProvision
// ppStream gets the passphrase stream from the cache
func (e *PaperProvisionEngine) ppStream(ctx *Context) (*libkb.PassphraseStream, error) {
	if ctx.LoginContext == nil {
		return nil, errors.New("loginProvision: ppStream() -> nil ctx.LoginContext")
	}
	cached := ctx.LoginContext.PassphraseStreamCache()
	if cached == nil {
		return nil, errors.New("loginProvision: ppStream() -> nil PassphraseStreamCache")
	}
	return cached.PassphraseStream(), nil
}
<commit_msg>Implemented Patrick's PR feedback<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

import (
	"errors"
	"fmt"

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

type PaperProvisionEngine struct {
	libkb.Contextified
	Username   string
	DeviceName string
	PaperKey   string
	result     error
	lks        *libkb.LKSec
	User       *libkb.User
}

func NewPaperProvisionEngine(g *libkb.GlobalContext, username, deviceName, paperKey string) *PaperProvisionEngine {
	return &PaperProvisionEngine{
		Contextified: libkb.NewContextified(g),
		Username:     username,
		DeviceName:   deviceName,
		PaperKey:     paperKey,
	}
}

func (e *PaperProvisionEngine) Name() string {
	return "PaperProvision"
}

func (e *PaperProvisionEngine) Prereqs() Prereqs {
	return Prereqs{}
}

func (e *PaperProvisionEngine) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{
		libkb.ProvisionUIKind,
		libkb.LogUIKind,
		libkb.SecretUIKind,
		libkb.LoginUIKind,
	}
}

func (e *PaperProvisionEngine) Run(ctx *Context) (err error) {
	e.G().Log.Debug("+ PaperProvisionEngine Run")

	defer e.G().Trace("PaperProvisionEngine#Run", func() error { return err })()

	// clear out any existing session:
	e.G().Logout()

	// transaction around config file
	tx, err := e.G().Env.GetConfigWriter().BeginTransaction()
	if err != nil {
		return err
	}

	// From this point on, if there's an error, we abort the
	// transaction.
	defer func() {
		if tx != nil {
			tx.Abort()
		}
	}()

	// run the LoginLoadUser sub-engine to load a user
	ueng := newLoginLoadUser(e.G(), e.Username)
	if err = RunEngine(ueng, ctx); err != nil {
		return err
	}

	// make sure the user isn't already provisioned (can
	// get here if usernameOrEmail is an email address
	// for an already provisioned on this device user).
	if ueng.User().HasCurrentDeviceInCurrentInstall() {
		return libkb.DeviceAlreadyProvisionedError{}
	}
	e.User = ueng.User()

	// Transform the paper key phrase into a key pair
	bkarg := &PaperKeyGenArg{
		Passphrase: libkb.PaperKeyPhrase(e.PaperKey),
		SkipPush:   true,
	}
	bkeng := NewPaperKeyGen(bkarg, e.G())
	if err := RunEngine(bkeng, ctx); err != nil {
		return err
	}

	kp := &keypair{sigKey: bkeng.SigKey(), encKey: bkeng.EncKey()}

	// Make sure the key matches the logged in user
	// use the KID to find the uid
	uid, err := e.uidByKID(kp.sigKey.GetKID())
	if err != nil {
		return err
	}

	if uid.NotEqual(e.User.GetUID()) {
		e.G().Log.Debug("paper key entered was for a different user")
		return fmt.Errorf("paper key valid, but for %s, not %s", uid, e.User.GetUID())
	}

	// Make new device keys and sign them with this paper key
	err = e.paper(ctx, kp)
	if err != nil {
		return err
	}

	// commit the config changes
	if err := tx.Commit(); err != nil {
		return err
	}

	// Zero out the TX so that we don't abort it in the defer()
	// exit.
	tx = nil

	e.sendNotification()
	return nil

}

// Copied from login_provision.go
func (e *PaperProvisionEngine) uidByKID(kid keybase1.KID) (keybase1.UID, error) {
	var nilUID keybase1.UID
	arg := libkb.APIArg{
		Endpoint:     "key/owner",
		NeedSession:  false,
		Contextified: libkb.NewContextified(e.G()),
		Args:         libkb.HTTPArgs{"kid": libkb.S{Val: kid.String()}},
	}
	res, err := e.G().API.Get(arg)
	if err != nil {
		return nilUID, err
	}
	suid, err := res.Body.AtPath("uid").GetString()
	if err != nil {
		return nilUID, err
	}
	return keybase1.UIDFromString(suid)
}

// copied more or less from loginProvision.paper()
func (e *PaperProvisionEngine) paper(ctx *Context, kp *keypair) error {
	// After obtaining login session, this will be called before the login state is released.
	// It signs this new device with the paper key.
	var afterLogin = func(lctx libkb.LoginContext) error {
		ctx.LoginContext = lctx

		// need lksec to store device keys locally
		if err := e.fetchLKS(ctx, kp.encKey); err != nil {
			return err
		}

		if err := e.makeDeviceKeysWithSigner(ctx, kp.sigKey); err != nil {
			return err
		}
		if err := e.G().LoginState().Account(func(a *libkb.Account) {
			a.SetUnlockedPaperKey(kp.sigKey, kp.encKey)
		}, "UnlockedPaperKey"); err != nil {
			return err
		}
		if err := lctx.LocalSession().SetDeviceProvisioned(e.G().Env.GetDeviceID()); err != nil {
			// not a fatal error, session will stay in memory
			e.G().Log.Warning("error saving session file: %s", err)
		}
		return nil
	}

	// need a session to continue to provision, login with paper sigKey
	return e.G().LoginState().LoginWithKey(ctx.LoginContext, e.User, kp.sigKey, afterLogin)
}

func (e *PaperProvisionEngine) sendNotification() {
	e.G().NotifyRouter.HandleLogin(string(e.G().Env.GetUsername()))
}

func (e *PaperProvisionEngine) SubConsumers() []libkb.UIConsumer {
	return []libkb.UIConsumer{
		&loginLoadUser{},
	}
}

func (e *PaperProvisionEngine) Result() error {
	return e.result
}

// copied from loginProvision
func (e *PaperProvisionEngine) fetchLKS(ctx *Context, encKey libkb.GenericKey) error {
	gen, clientLKS, err := fetchLKS(ctx, e.G(), encKey)
	if err != nil {
		return err
	}
	e.lks = libkb.NewLKSecWithClientHalf(clientLKS, gen, e.User.GetUID(), e.G())
	return nil
}

// copied from loginProvision
// makeDeviceKeysWithSigner creates device keys given a signing
// key.
func (e *PaperProvisionEngine) makeDeviceKeysWithSigner(ctx *Context, signer libkb.GenericKey) error {
	args, err := e.makeDeviceWrapArgs(ctx)
	if err != nil {
		return err
	}
	args.Signer = signer
	args.IsEldest = false // just to be explicit
	args.EldestKID = e.User.GetEldestKID()

	return e.makeDeviceKeys(ctx, args)
}

// copied from loginProvision
// makeDeviceWrapArgs creates a base set of args for DeviceWrap.
// It ensures that LKSec is created.  It also gets a new device
// name for this device.
func (e *PaperProvisionEngine) makeDeviceWrapArgs(ctx *Context) (*DeviceWrapArgs, error) {
	if err := e.ensureLKSec(ctx); err != nil {
		return nil, err
	}

	return &DeviceWrapArgs{
		Me:         e.User,
		DeviceName: e.DeviceName,
		DeviceType: "desktop",
		Lks:        e.lks,
	}, nil
}

// copied from loginProvision
// makeDeviceKeys uses DeviceWrap to generate device keys.
func (e *PaperProvisionEngine) makeDeviceKeys(ctx *Context, args *DeviceWrapArgs) error {
	eng := NewDeviceWrap(args, e.G())
	if err := RunEngine(eng, ctx); err != nil {
		return err
	}

	return nil
}

// copied from loginProvision
// ensureLKSec ensures we have LKSec for saving device keys.
func (e *PaperProvisionEngine) ensureLKSec(ctx *Context) error {
	if e.lks != nil {
		return nil
	}

	pps, err := e.ppStream(ctx)
	if err != nil {
		return err
	}

	e.lks = libkb.NewLKSec(pps, e.User.GetUID(), e.G())
	return nil
}

// copied from loginProvision
// ppStream gets the passphrase stream from the cache
func (e *PaperProvisionEngine) ppStream(ctx *Context) (*libkb.PassphraseStream, error) {
	if ctx.LoginContext == nil {
		return nil, errors.New("loginProvision: ppStream() -> nil ctx.LoginContext")
	}
	cached := ctx.LoginContext.PassphraseStreamCache()
	if cached == nil {
		return nil, errors.New("loginProvision: ppStream() -> nil PassphraseStreamCache")
	}
	return cached.PassphraseStream(), nil
}
<|endoftext|>


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

// Copyright 2009 The Go 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 signal implements operating system-independent signal handling.
package sighandler

import (
	"os"
	"os/signal"
	"sync"
	"syscall"
)

type SignalHandler func(signal os.Signal)

// Registered handlers will be dispatched automatically when a signal arrives.
var mutex sync.Mutex
var signalHandlerMap map[os.Signal]SignalHandler

func init() {
	signalHandlerMap = make(map[os.Signal]SignalHandler)
	SetSignalHandler(syscall.SIGINT, DefaultSignalHandler)
	SetSignalHandler(syscall.SIGTERM, DefaultSignalHandler)
	c := make(chan os.Signal)
	signal.Notify(c)
	go signalDispatcher(c)
}

func DefaultSignalHandler(signal os.Signal) {
	os.Exit(2)
}

func signalDispatcher(signalChan <-chan os.Signal) {
	for sig := range signalChan {
		mutex.Lock()
		sigHandler, ok := signalHandlerMap[sig]
		mutex.Unlock()
		if ok {
			sigHandler(sig)
		}
	}
}

func SetSignalHandler(signal os.Signal, signalHandler SignalHandler) SignalHandler {
	mutex.Lock()
	defer mutex.Unlock()

	oldHandler, _ := signalHandlerMap[signal]
	signalHandlerMap[signal] = signalHandler
	return oldHandler
}

func ClearSignalHandler(signal os.Signal) {
	mutex.Lock()
	defer mutex.Unlock()

	delete(signalHandlerMap, signal)
}
<commit_msg>remove unnecessary module<commit_after><|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/dag"
)

// DiffTransformer is a GraphTransformer that adds the elements of
// the diff to the graph.
//
// This transform is used for example by the ApplyGraphBuilder to ensure
// that only resources that are being modified are represented in the graph.
type DiffTransformer struct {
	Concrete ConcreteResourceInstanceNodeFunc
	Diff     *Diff
}

func (t *DiffTransformer) Transform(g *Graph) error {
	// If the diff is nil or empty (nil is empty) then do nothing
	if t.Diff.Empty() {
		return nil
	}

	// Go through all the modules in the diff.
	log.Printf("[TRACE] DiffTransformer: starting")
	var nodes []dag.Vertex
	for _, m := range t.Diff.Modules {
		log.Printf("[TRACE] DiffTransformer: Module: %s", m)
		// TODO: If this is a destroy diff then add a module destroy node

		// Go through all the resources in this module.
		for name, inst := range m.Resources {
			log.Printf("[TRACE] DiffTransformer: Resource %q: %#v", name, inst)

			// We have changes! This is a create or update operation.
			// First grab the address so we have a unique way to
			// reference this resource.
			legacyAddr, err := parseResourceAddressInternal(name)
			if err != nil {
				panic(fmt.Sprintf(
					"Error parsing internal name, this is a bug: %q", name))
			}
			addr := legacyAddr.AbsResourceInstanceAddr()

			// If we're destroying, add the destroy node
			if inst.Destroy || inst.GetDestroyDeposed() {
				abstract := NewNodeAbstractResourceInstance(addr)
				g.Add(&NodeDestroyResourceInstance{NodeAbstractResourceInstance: abstract})
			}

			// If we have changes, then add the applyable version
			if len(inst.Attributes) > 0 {
				// Add the resource to the graph
				abstract := NewNodeAbstractResourceInstance(addr)
				var node dag.Vertex = abstract
				if f := t.Concrete; f != nil {
					node = f(abstract)
				}

				nodes = append(nodes, node)
			}
		}
	}

	// Add all the nodes to the graph
	for _, n := range nodes {
		g.Add(n)
	}

	return nil
}
<commit_msg>core: Fix DiffTransformer node addresses<commit_after>package terraform

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/dag"
)

// DiffTransformer is a GraphTransformer that adds the elements of
// the diff to the graph.
//
// This transform is used for example by the ApplyGraphBuilder to ensure
// that only resources that are being modified are represented in the graph.
type DiffTransformer struct {
	Concrete ConcreteResourceInstanceNodeFunc
	Diff     *Diff
}

func (t *DiffTransformer) Transform(g *Graph) error {
	// If the diff is nil or empty (nil is empty) then do nothing
	if t.Diff.Empty() {
		return nil
	}

	// Go through all the modules in the diff.
	log.Printf("[TRACE] DiffTransformer: starting")
	var nodes []dag.Vertex
	for _, m := range t.Diff.Modules {
		log.Printf("[TRACE] DiffTransformer: Module: %s", m)
		// TODO: If this is a destroy diff then add a module destroy node

		// Go through all the resources in this module.
		for name, inst := range m.Resources {
			log.Printf("[TRACE] DiffTransformer: Resource %q: %#v", name, inst)

			// We have changes! This is a create or update operation.
			// First grab the address so we have a unique way to
			// reference this resource.
			legacyAddr, err := parseResourceAddressInternal(name)
			if err != nil {
				panic(fmt.Sprintf(
					"Error parsing internal name, this is a bug: %q", name))
			}

			// legacyAddr is relative even though the legacy ResourceAddress is
			// usually absolute, so we need to do some trickery here to get
			// a new-style absolute address in the right module.
			// FIXME: Clean this up once the "Diff" types are updated to use
			// our new address types.
			addr := legacyAddr.AbsResourceInstanceAddr()
			addr = addr.Resource.Absolute(normalizeModulePath(m.Path))

			// If we're destroying, add the destroy node
			if inst.Destroy || inst.GetDestroyDeposed() {
				abstract := NewNodeAbstractResourceInstance(addr)
				g.Add(&NodeDestroyResourceInstance{NodeAbstractResourceInstance: abstract})
			}

			// If we have changes, then add the applyable version
			if len(inst.Attributes) > 0 {
				// Add the resource to the graph
				abstract := NewNodeAbstractResourceInstance(addr)
				var node dag.Vertex = abstract
				if f := t.Concrete; f != nil {
					node = f(abstract)
				}

				nodes = append(nodes, node)
			}
		}
	}

	// Add all the nodes to the graph
	for _, n := range nodes {
		g.Add(n)
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go 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 syscall contains an interface to the low-level operating system
// primitives.  The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net".  Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
// These calls return err == nil to indicate success; otherwise
// err is an operating system error describing the failure.
// On most systems, that error has type syscall.Errno.
package syscall

// StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s.
func StringByteSlice(s string) []byte {
	a := make([]byte, len(s)+1)
	copy(a, s)
	return a
}

// StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }

// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr

func (ts *Timespec) Unix() (sec int64, nsec int64) {
	return int64(ts.Sec), int64(ts.Nsec)
}

func (tv *Timeval) Unix() (sec int64, nsec int64) {
	return int64(tv.Sec), int64(tv.Usec) * 1000
}
<commit_msg>syscall: add Timeval.Nano, Timespec.Nano, for conversion to Duration<commit_after>// Copyright 2009 The Go 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 syscall contains an interface to the low-level operating system
// primitives.  The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net".  Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
// These calls return err == nil to indicate success; otherwise
// err is an operating system error describing the failure.
// On most systems, that error has type syscall.Errno.
package syscall

// StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s.
func StringByteSlice(s string) []byte {
	a := make([]byte, len(s)+1)
	copy(a, s)
	return a
}

// StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }

// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr

func (ts *Timespec) Unix() (sec int64, nsec int64) {
	return int64(ts.Sec), int64(ts.Nsec)
}

func (tv *Timeval) Unix() (sec int64, nsec int64) {
	return int64(tv.Sec), int64(tv.Usec) * 1000
}

func (ts *Timespec) Nano() int64 {
	return int64(ts.Sec)*1e9 + int64(ts.Nsec)
}

func (tv *Timeval) Nano() int64 {
	return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go 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 time_test

import (
	"errors"
	"fmt"
	"runtime"
	"sort"
	"sync"
	"sync/atomic"
	"testing"
	. "time"
)

func TestSleep(t *testing.T) {
	const delay = 100 * Millisecond
	go func() {
		Sleep(delay / 2)
		Interrupt()
	}()
	start := Now()
	Sleep(delay)
	duration := Now().Sub(start)
	if duration < delay {
		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
	}
}

// Test the basic function calling behavior. Correct queueing
// behavior is tested elsewhere, since After and AfterFunc share
// the same code.
func TestAfterFunc(t *testing.T) {
	i := 10
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
			Sleep(1 * Second)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func TestAfterStress(t *testing.T) {
	stop := uint32(0)
	go func() {
		for atomic.LoadUint32(&stop) == 0 {
			runtime.GC()
			// Yield so that the OS can wake up the timer thread,
			// so that it can generate channel sends for the main goroutine,
			// which will eventually set stop = 1 for us.
			Sleep(Nanosecond)
		}
	}()
	ticker := NewTicker(1)
	for i := 0; i < 100; i++ {
		<-ticker.C
	}
	ticker.Stop()
	atomic.StoreUint32(&stop, 1)
}

func benchmark(b *testing.B, bench func(n int)) {
	garbage := make([]*Timer, 1<<17)
	for i := 0; i < len(garbage); i++ {
		garbage[i] = AfterFunc(Hour, nil)
	}

	const batch = 1000
	P := runtime.GOMAXPROCS(-1)
	N := int32(b.N / batch)

	b.ResetTimer()

	var wg sync.WaitGroup
	wg.Add(P)

	for p := 0; p < P; p++ {
		go func() {
			for atomic.AddInt32(&N, -1) >= 0 {
				bench(batch)
			}
			wg.Done()
		}()
	}

	wg.Wait()

	b.StopTimer()
	for i := 0; i < len(garbage); i++ {
		garbage[i].Stop()
	}
}

func BenchmarkAfterFunc(b *testing.B) {
	benchmark(b, func(n int) {
		c := make(chan bool)
		var f func()
		f = func() {
			n--
			if n >= 0 {
				AfterFunc(0, f)
			} else {
				c <- true
			}
		}

		AfterFunc(0, f)
		<-c
	})
}

func BenchmarkAfter(b *testing.B) {
	benchmark(b, func(n int) {
		for i := 0; i < n; i++ {
			<-After(1)
		}
	})
}

func BenchmarkStop(b *testing.B) {
	benchmark(b, func(n int) {
		for i := 0; i < n; i++ {
			NewTimer(1 * Second).Stop()
		}
	})
}

func BenchmarkSimultaneousAfterFunc(b *testing.B) {
	benchmark(b, func(n int) {
		var wg sync.WaitGroup
		wg.Add(n)
		for i := 0; i < n; i++ {
			AfterFunc(0, wg.Done)
		}
		wg.Wait()
	})
}

func BenchmarkStartStop(b *testing.B) {
	benchmark(b, func(n int) {
		timers := make([]*Timer, n)
		for i := 0; i < n; i++ {
			timers[i] = AfterFunc(Hour, nil)
		}

		for i := 0; i < n; i++ {
			timers[i].Stop()
		}
	})
}

func TestAfter(t *testing.T) {
	const delay = 100 * Millisecond
	start := Now()
	end := <-After(delay)
	if duration := Now().Sub(start); duration < delay {
		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
	}
	if min := start.Add(delay); end.Before(min) {
		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
	}
}

func TestAfterTick(t *testing.T) {
	const Count = 10
	Delta := 100 * Millisecond
	if testing.Short() {
		Delta = 10 * Millisecond
	}
	t0 := Now()
	for i := 0; i < Count; i++ {
		<-After(Delta)
	}
	t1 := Now()
	d := t1.Sub(t0)
	target := Delta * Count
	if d < target*9/10 {
		t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
	}
	if !testing.Short() && d > target*30/10 {
		t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
	}
}

func TestAfterStop(t *testing.T) {
	AfterFunc(100*Millisecond, func() {})
	t0 := NewTimer(50 * Millisecond)
	c1 := make(chan bool, 1)
	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
	c2 := After(200 * Millisecond)
	if !t0.Stop() {
		t.Fatalf("failed to stop event 0")
	}
	if !t1.Stop() {
		t.Fatalf("failed to stop event 1")
	}
	<-c2
	select {
	case <-t0.C:
		t.Fatalf("event 0 was not stopped")
	case <-c1:
		t.Fatalf("event 1 was not stopped")
	default:
	}
	if t1.Stop() {
		t.Fatalf("Stop returned true twice")
	}
}

func TestAfterQueuing(t *testing.T) {
	// This test flakes out on some systems,
	// so we'll try it a few times before declaring it a failure.
	const attempts = 3
	err := errors.New("!=nil")
	for i := 0; i < attempts && err != nil; i++ {
		if err = testAfterQueuing(t); err != nil {
			t.Logf("attempt %v failed: %v", i, err)
		}
	}
	if err != nil {
		t.Fatal(err)
	}
}

var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}

type afterResult struct {
	slot int
	t    Time
}

func await(slot int, result chan<- afterResult, ac <-chan Time) {
	result <- afterResult{slot, <-ac}
}

func testAfterQueuing(t *testing.T) error {
	Delta := 100 * Millisecond
	if testing.Short() {
		Delta = 20 * Millisecond
	}
	// make the result channel buffered because we don't want
	// to depend on channel queueing semantics that might
	// possibly change in the future.
	result := make(chan afterResult, len(slots))

	t0 := Now()
	for _, slot := range slots {
		go await(slot, result, After(Duration(slot)*Delta))
	}
	sort.Ints(slots)
	for _, slot := range slots {
		r := <-result
		if r.slot != slot {
			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
		}
		dt := r.t.Sub(t0)
		target := Duration(slot) * Delta
		if dt < target-Delta/2 || dt > target+Delta*10 {
			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
		}
	}
	return nil
}

func TestTimerStopStress(t *testing.T) {
	if testing.Short() {
		return
	}
	for i := 0; i < 100; i++ {
		go func(i int) {
			timer := AfterFunc(2*Second, func() {
				t.Fatalf("timer %d was not stopped", i)
			})
			Sleep(1 * Second)
			timer.Stop()
		}(i)
	}
	Sleep(3 * Second)
}

func TestSleepZeroDeadlock(t *testing.T) {
	// Sleep(0) used to hang, the sequence of events was as follows.
	// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
	// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
	// After the GC nobody wakes up the goroutine from Gwaiting status.
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
	c := make(chan bool)
	go func() {
		for i := 0; i < 100; i++ {
			runtime.GC()
		}
		c <- true
	}()
	for i := 0; i < 100; i++ {
		Sleep(0)
		tmp := make(chan bool, 1)
		tmp <- true
		<-tmp
	}
	<-c
}

func testReset(d Duration) error {
	t0 := NewTimer(2 * d)
	Sleep(d)
	if t0.Reset(3*d) != true {
		return errors.New("resetting unfired timer returned false")
	}
	Sleep(2 * d)
	select {
	case <-t0.C:
		return errors.New("timer fired early")
	default:
	}
	Sleep(2 * d)
	select {
	case <-t0.C:
	default:
		return errors.New("reset timer did not fire")
	}

	if t0.Reset(50*Millisecond) != false {
		return errors.New("resetting expired timer returned true")
	}
	return nil
}

func TestReset(t *testing.T) {
	// We try to run this test with increasingly larger multiples
	// until one works so slow, loaded hardware isn't as flaky,
	// but without slowing down fast machines unnecessarily.
	const unit = 25 * Millisecond
	tries := []Duration{
		1 * unit,
		3 * unit,
		7 * unit,
		15 * unit,
	}
	var err error
	for _, d := range tries {
		err = testReset(d)
		if err == nil {
			t.Logf("passed using duration %v", d)
			return
		}
	}
	t.Error(err)
}

// Test that sleeping for an interval so large it overflows does not
// result in a short sleep duration.
func TestOverflowSleep(t *testing.T) {
	const timeout = 25 * Millisecond
	const big = Duration(int64(1<<63 - 1))
	select {
	case <-After(big):
		t.Fatalf("big timeout fired")
	case <-After(timeout):
		// OK
	}
	const neg = Duration(-1 << 63)
	select {
	case <-After(neg):
		// OK
	case <-After(timeout):
		t.Fatalf("negative timeout didn't fire")
	}
}

// Test that a panic while deleting a timer does not leave
// the timers mutex held, deadlocking a ticker.Stop in a defer.
func TestIssue5745(t *testing.T) {
	ticker := NewTicker(Hour)
	defer func() {
		// would deadlock here before the fix due to
		// lock taken before the segfault.
		ticker.Stop()

		if r := recover(); r == nil {
			t.Error("Expected panic, but none happened.")
		}
	}()

	// cause a panic due to a segfault
	var timer *Timer
	timer.Stop()
	t.Error("Should be unreachable.")
}

func TestOverflowRuntimeTimer(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode, see issue 6874")
	}
	if err := CheckRuntimeTimerOverflow(); err != nil {
		t.Fatalf(err.Error())
	}
}
<commit_msg>time: use RunParallel in benchmarks<commit_after>// Copyright 2009 The Go 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 time_test

import (
	"errors"
	"fmt"
	"runtime"
	"sort"
	"sync"
	"sync/atomic"
	"testing"
	. "time"
)

func TestSleep(t *testing.T) {
	const delay = 100 * Millisecond
	go func() {
		Sleep(delay / 2)
		Interrupt()
	}()
	start := Now()
	Sleep(delay)
	duration := Now().Sub(start)
	if duration < delay {
		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
	}
}

// Test the basic function calling behavior. Correct queueing
// behavior is tested elsewhere, since After and AfterFunc share
// the same code.
func TestAfterFunc(t *testing.T) {
	i := 10
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
			Sleep(1 * Second)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func TestAfterStress(t *testing.T) {
	stop := uint32(0)
	go func() {
		for atomic.LoadUint32(&stop) == 0 {
			runtime.GC()
			// Yield so that the OS can wake up the timer thread,
			// so that it can generate channel sends for the main goroutine,
			// which will eventually set stop = 1 for us.
			Sleep(Nanosecond)
		}
	}()
	ticker := NewTicker(1)
	for i := 0; i < 100; i++ {
		<-ticker.C
	}
	ticker.Stop()
	atomic.StoreUint32(&stop, 1)
}

func benchmark(b *testing.B, bench func(n int)) {
	garbage := make([]*Timer, 1<<17)
	for i := 0; i < len(garbage); i++ {
		garbage[i] = AfterFunc(Hour, nil)
	}
	b.ResetTimer()

	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			bench(1000)
		}
	})

	b.StopTimer()
	for i := 0; i < len(garbage); i++ {
		garbage[i].Stop()
	}
}

func BenchmarkAfterFunc(b *testing.B) {
	benchmark(b, func(n int) {
		c := make(chan bool)
		var f func()
		f = func() {
			n--
			if n >= 0 {
				AfterFunc(0, f)
			} else {
				c <- true
			}
		}

		AfterFunc(0, f)
		<-c
	})
}

func BenchmarkAfter(b *testing.B) {
	benchmark(b, func(n int) {
		for i := 0; i < n; i++ {
			<-After(1)
		}
	})
}

func BenchmarkStop(b *testing.B) {
	benchmark(b, func(n int) {
		for i := 0; i < n; i++ {
			NewTimer(1 * Second).Stop()
		}
	})
}

func BenchmarkSimultaneousAfterFunc(b *testing.B) {
	benchmark(b, func(n int) {
		var wg sync.WaitGroup
		wg.Add(n)
		for i := 0; i < n; i++ {
			AfterFunc(0, wg.Done)
		}
		wg.Wait()
	})
}

func BenchmarkStartStop(b *testing.B) {
	benchmark(b, func(n int) {
		timers := make([]*Timer, n)
		for i := 0; i < n; i++ {
			timers[i] = AfterFunc(Hour, nil)
		}

		for i := 0; i < n; i++ {
			timers[i].Stop()
		}
	})
}

func TestAfter(t *testing.T) {
	const delay = 100 * Millisecond
	start := Now()
	end := <-After(delay)
	if duration := Now().Sub(start); duration < delay {
		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
	}
	if min := start.Add(delay); end.Before(min) {
		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
	}
}

func TestAfterTick(t *testing.T) {
	const Count = 10
	Delta := 100 * Millisecond
	if testing.Short() {
		Delta = 10 * Millisecond
	}
	t0 := Now()
	for i := 0; i < Count; i++ {
		<-After(Delta)
	}
	t1 := Now()
	d := t1.Sub(t0)
	target := Delta * Count
	if d < target*9/10 {
		t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
	}
	if !testing.Short() && d > target*30/10 {
		t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
	}
}

func TestAfterStop(t *testing.T) {
	AfterFunc(100*Millisecond, func() {})
	t0 := NewTimer(50 * Millisecond)
	c1 := make(chan bool, 1)
	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
	c2 := After(200 * Millisecond)
	if !t0.Stop() {
		t.Fatalf("failed to stop event 0")
	}
	if !t1.Stop() {
		t.Fatalf("failed to stop event 1")
	}
	<-c2
	select {
	case <-t0.C:
		t.Fatalf("event 0 was not stopped")
	case <-c1:
		t.Fatalf("event 1 was not stopped")
	default:
	}
	if t1.Stop() {
		t.Fatalf("Stop returned true twice")
	}
}

func TestAfterQueuing(t *testing.T) {
	// This test flakes out on some systems,
	// so we'll try it a few times before declaring it a failure.
	const attempts = 3
	err := errors.New("!=nil")
	for i := 0; i < attempts && err != nil; i++ {
		if err = testAfterQueuing(t); err != nil {
			t.Logf("attempt %v failed: %v", i, err)
		}
	}
	if err != nil {
		t.Fatal(err)
	}
}

var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}

type afterResult struct {
	slot int
	t    Time
}

func await(slot int, result chan<- afterResult, ac <-chan Time) {
	result <- afterResult{slot, <-ac}
}

func testAfterQueuing(t *testing.T) error {
	Delta := 100 * Millisecond
	if testing.Short() {
		Delta = 20 * Millisecond
	}
	// make the result channel buffered because we don't want
	// to depend on channel queueing semantics that might
	// possibly change in the future.
	result := make(chan afterResult, len(slots))

	t0 := Now()
	for _, slot := range slots {
		go await(slot, result, After(Duration(slot)*Delta))
	}
	sort.Ints(slots)
	for _, slot := range slots {
		r := <-result
		if r.slot != slot {
			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
		}
		dt := r.t.Sub(t0)
		target := Duration(slot) * Delta
		if dt < target-Delta/2 || dt > target+Delta*10 {
			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
		}
	}
	return nil
}

func TestTimerStopStress(t *testing.T) {
	if testing.Short() {
		return
	}
	for i := 0; i < 100; i++ {
		go func(i int) {
			timer := AfterFunc(2*Second, func() {
				t.Fatalf("timer %d was not stopped", i)
			})
			Sleep(1 * Second)
			timer.Stop()
		}(i)
	}
	Sleep(3 * Second)
}

func TestSleepZeroDeadlock(t *testing.T) {
	// Sleep(0) used to hang, the sequence of events was as follows.
	// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
	// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
	// After the GC nobody wakes up the goroutine from Gwaiting status.
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
	c := make(chan bool)
	go func() {
		for i := 0; i < 100; i++ {
			runtime.GC()
		}
		c <- true
	}()
	for i := 0; i < 100; i++ {
		Sleep(0)
		tmp := make(chan bool, 1)
		tmp <- true
		<-tmp
	}
	<-c
}

func testReset(d Duration) error {
	t0 := NewTimer(2 * d)
	Sleep(d)
	if t0.Reset(3*d) != true {
		return errors.New("resetting unfired timer returned false")
	}
	Sleep(2 * d)
	select {
	case <-t0.C:
		return errors.New("timer fired early")
	default:
	}
	Sleep(2 * d)
	select {
	case <-t0.C:
	default:
		return errors.New("reset timer did not fire")
	}

	if t0.Reset(50*Millisecond) != false {
		return errors.New("resetting expired timer returned true")
	}
	return nil
}

func TestReset(t *testing.T) {
	// We try to run this test with increasingly larger multiples
	// until one works so slow, loaded hardware isn't as flaky,
	// but without slowing down fast machines unnecessarily.
	const unit = 25 * Millisecond
	tries := []Duration{
		1 * unit,
		3 * unit,
		7 * unit,
		15 * unit,
	}
	var err error
	for _, d := range tries {
		err = testReset(d)
		if err == nil {
			t.Logf("passed using duration %v", d)
			return
		}
	}
	t.Error(err)
}

// Test that sleeping for an interval so large it overflows does not
// result in a short sleep duration.
func TestOverflowSleep(t *testing.T) {
	const timeout = 25 * Millisecond
	const big = Duration(int64(1<<63 - 1))
	select {
	case <-After(big):
		t.Fatalf("big timeout fired")
	case <-After(timeout):
		// OK
	}
	const neg = Duration(-1 << 63)
	select {
	case <-After(neg):
		// OK
	case <-After(timeout):
		t.Fatalf("negative timeout didn't fire")
	}
}

// Test that a panic while deleting a timer does not leave
// the timers mutex held, deadlocking a ticker.Stop in a defer.
func TestIssue5745(t *testing.T) {
	ticker := NewTicker(Hour)
	defer func() {
		// would deadlock here before the fix due to
		// lock taken before the segfault.
		ticker.Stop()

		if r := recover(); r == nil {
			t.Error("Expected panic, but none happened.")
		}
	}()

	// cause a panic due to a segfault
	var timer *Timer
	timer.Stop()
	t.Error("Should be unreachable.")
}

func TestOverflowRuntimeTimer(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode, see issue 6874")
	}
	if err := CheckRuntimeTimerOverflow(); err != nil {
		t.Fatalf(err.Error())
	}
}
<|endoftext|>


<commit_before>package themes

// Functions directly related to HTML, CSS, Amber or GCSS

import (
	"bytes"
	"fmt"
	"strings"
)

const (
	// DefaultCSSFilename is the default CSS stylesheet
	DefaultCSSFilename = "style.css"

	// DefaultGCSSFilename is the default GCSS stylesheet
	DefaultGCSSFilename = "style.gcss"

	// DefaultTheme is the default theme when rendering Markdown and for error pages
	DefaultTheme = "default"
)

var (
	// MetaKeywords contains a selection of allowed keywords for the HTML meta tag
	MetaKeywords = []string{"application-name", "author", "description", "generator", "keywords", "robots", "language", "googlebot", "Slurp", "bingbot", "geo.position", "geo.placename", "geo.region", "ICBM", "viewport"}
)

// MessagePage is an easy way to output a HTML page only given a title, the body
// (will be placed between the  tags) and the name of one of the
// built-in themes. Does not close  and .
// Deprecated
func MessagePage(title, body, theme string) string {
	return fmt.Sprintf("<!doctype html><title>%s</title>%s
%s
%s", title, StyleHead(theme), title, body)
}

// StyleHead returns contents that goes in "", as bytes.
// This is either CSS wrapped in a "")
		buf.WriteString("<link rel=\"stylesheet\" href=\"" + theme + "\">")
	} else {
		buf.WriteString("")
	}
	return buf.Bytes()
}

// MessagePageBytes provides the same functionalityt as MessagePage,
// but with []byte instead of string, and without closing
func MessagePageBytes(title string, body []byte, theme string) []byte {
	var buf bytes.Buffer
	buf.WriteString("<!doctype html><title>")
	buf.WriteString(title)
	buf.WriteString("</title>")
	buf.Write(StyleHead(theme))
	buf.WriteString("
")
	buf.WriteString(title)
	buf.WriteString("
")
	buf.Write(body)
	return buf.Bytes()
}

// SimpleHTMLPage provides a quick way to build a HTML page
func SimpleHTMLPage(title, headline, inhead, body []byte) []byte {
	var buf bytes.Buffer
	buf.WriteString("<!doctype html><title>")
	buf.Write(title)
	buf.WriteString("</title>")
	buf.Write(inhead)
	buf.WriteString("
")
	buf.Write(headline)
	buf.WriteString("
")
	buf.Write(body)
	return buf.Bytes()
}

// HTMLLink builds an HTML link given the link text, the URL to a file/directory
// and a boolean that is true if the given URL is to a directory.
func HTMLLink(text, url string, isDirectory bool) string {
	// Add a final slash, if needed
	if isDirectory {
		text += "/"
		url += "/"
	}
	return "" + text + "
"
}

// StyleAmber modifies Amber source code so that a link to the given stylesheet URL is added
func StyleAmber(amberdata []byte, url string) []byte {
	// If the given url is not already mentioned and the data contains "body"
	if !bytes.Contains(amberdata, []byte(url)) && bytes.Contains(amberdata, []byte("html")) && bytes.Contains(amberdata, []byte("body")) {
		// Extract one level of indendation
		whitespace := OneLevelOfIndentation(&amberdata, "body")
		// Check if there already is a head section
		if bytes.Contains(amberdata, []byte("head")) {
			// Add a link to the stylesheet
			return bytes.Replace(amberdata, []byte("head\n"), []byte("head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)

		} else if bytes.Contains(amberdata, []byte("body")) {

			// Add a link to the stylesheet
			return bytes.Replace(amberdata, []byte("html\n"), []byte("html\n"+whitespace+"head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)
		}
	}
	return amberdata
}

// StyleHTML modifies HTML source code so that a link to the given stylesheet URL is added
func StyleHTML(htmldata []byte, url string) []byte {
	// If the given url is not already mentioned and the data contains "body"
	if !bytes.Contains(htmldata, []byte(url)) && bytes.Contains(htmldata, []byte("body")) {
		if bytes.Contains(htmldata, []byte("")) {
			return bytes.Replace(htmldata, []byte(""), []byte("  <link rel=\"stylesheet\" href=\""+url+"\">\n  "), 1)
		} else if bytes.Contains(htmldata, []byte("")) {
			return bytes.Replace(htmldata, []byte(""), []byte("  \n  <link rel=\"stylesheet\" href=\""+url+"\">\n  \n  "), 1)
		}
	}
	return htmldata
}

// InsertDoctype inserts <doctype html> to the HTML, if missing.
// Does not check if the given data is HTML. Assumes it to be HTML.
func InsertDoctype(htmldata []byte) []byte {
	// If there are more than two lines
	if bytes.Count(htmldata, []byte("\n")) > 2 {
		fields := bytes.SplitN(htmldata, []byte("\n"), 3)
		line1 := strings.ToLower(string(fields[0]))
		line2 := strings.ToLower(string(fields[1]))
		if strings.Contains(line1, "doctype") || strings.Contains(line2, "doctype") {
			return htmldata
		}
		// Doctype is missing from the first two lines, add it
		return []byte("<!doctype html>\n" + string(htmldata))
	}
	return htmldata
}

// NoPage provides the same functionality as NoPage, but returns []byte
func NoPage(filename, theme string) []byte {
	return MessagePageBytes("Not found", []byte("File not found: "+filename), theme)
}
<commit_msg>Rename a variable<commit_after>package themes

// Functions directly related to HTML, CSS, Amber or GCSS

import (
	"bytes"
	"fmt"
	"strings"
)

const (
	// DefaultCSSFilename is the default CSS stylesheet
	DefaultCSSFilename = "style.css"

	// DefaultGCSSFilename is the default GCSS stylesheet
	DefaultGCSSFilename = "style.gcss"

	// DefaultTheme is the default theme when rendering Markdown and for error pages
	DefaultTheme = "default"
)

var (
	// MetaKeywords contains a selection of allowed keywords for the HTML meta tag
	MetaKeywords = []string{"application-name", "author", "description", "generator", "keywords", "robots", "language", "googlebot", "Slurp", "bingbot", "geo.position", "geo.placename", "geo.region", "ICBM", "viewport"}
)

// MessagePage is an easy way to output a HTML page only given a title, the body
// (will be placed between the  tags) and the name of one of the
// built-in themes. Does not close  and .
// Deprecated
func MessagePage(title, body, theme string) string {
	return fmt.Sprintf("<!doctype html><title>%s</title>%s
%s
%s", title, StyleHead(theme), title, body)
}

// StyleHead returns contents that goes in "", as bytes.
// This is either CSS wrapped in a "")
		buf.WriteString("<link rel=\"stylesheet\" href=\"" + theme + "\">")
	} else {
		buf.WriteString("")
	}
	return buf.Bytes()
}

// MessagePageBytes provides the same functionalityt as MessagePage,
// but with []byte instead of string, and without closing
func MessagePageBytes(title string, body []byte, theme string) []byte {
	var buf bytes.Buffer
	buf.WriteString("<!doctype html><title>")
	buf.WriteString(title)
	buf.WriteString("</title>")
	buf.Write(StyleHead(theme))
	buf.WriteString("
")
	buf.WriteString(title)
	buf.WriteString("
")
	buf.Write(body)
	return buf.Bytes()
}

// SimpleHTMLPage provides a quick way to build a HTML page
func SimpleHTMLPage(title, headline, inhead, body []byte) []byte {
	var buf bytes.Buffer
	buf.WriteString("<!doctype html><title>")
	buf.Write(title)
	buf.WriteString("</title>")
	buf.Write(inhead)
	buf.WriteString("
")
	buf.Write(headline)
	buf.WriteString("
")
	buf.Write(body)
	return buf.Bytes()
}

// HTMLLink builds an HTML link given the link text, the URL to a file/directory
// and a boolean that is true if the given URL is to a directory.
func HTMLLink(text, URL string, isDirectory bool) string {
	// Add a final slash, if needed
	if isDirectory {
		text += "/"
		URL += "/"
	}
	return "" + text + "
"
}

// StyleAmber modifies Amber source code so that a link to the given stylesheet URL is added
func StyleAmber(amberdata []byte, url string) []byte {
	// If the given url is not already mentioned and the data contains "body"
	if !bytes.Contains(amberdata, []byte(url)) && bytes.Contains(amberdata, []byte("html")) && bytes.Contains(amberdata, []byte("body")) {
		// Extract one level of indendation
		whitespace := OneLevelOfIndentation(&amberdata, "body")
		// Check if there already is a head section
		if bytes.Contains(amberdata, []byte("head")) {
			// Add a link to the stylesheet
			return bytes.Replace(amberdata, []byte("head\n"), []byte("head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)

		} else if bytes.Contains(amberdata, []byte("body")) {

			// Add a link to the stylesheet
			return bytes.Replace(amberdata, []byte("html\n"), []byte("html\n"+whitespace+"head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)
		}
	}
	return amberdata
}

// StyleHTML modifies HTML source code so that a link to the given stylesheet URL is added
func StyleHTML(htmldata []byte, url string) []byte {
	// If the given url is not already mentioned and the data contains "body"
	if !bytes.Contains(htmldata, []byte(url)) && bytes.Contains(htmldata, []byte("body")) {
		if bytes.Contains(htmldata, []byte("")) {
			return bytes.Replace(htmldata, []byte(""), []byte("  <link rel=\"stylesheet\" href=\""+url+"\">\n  "), 1)
		} else if bytes.Contains(htmldata, []byte("")) {
			return bytes.Replace(htmldata, []byte(""), []byte("  \n  <link rel=\"stylesheet\" href=\""+url+"\">\n  \n  "), 1)
		}
	}
	return htmldata
}

// InsertDoctype inserts <doctype html> to the HTML, if missing.
// Does not check if the given data is HTML. Assumes it to be HTML.
func InsertDoctype(htmldata []byte) []byte {
	// If there are more than two lines
	if bytes.Count(htmldata, []byte("\n")) > 2 {
		fields := bytes.SplitN(htmldata, []byte("\n"), 3)
		line1 := strings.ToLower(string(fields[0]))
		line2 := strings.ToLower(string(fields[1]))
		if strings.Contains(line1, "doctype") || strings.Contains(line2, "doctype") {
			return htmldata
		}
		// Doctype is missing from the first two lines, add it
		return []byte("<!doctype html>\n" + string(htmldata))
	}
	return htmldata
}

// NoPage provides the same functionality as NoPage, but returns []byte
func NoPage(filename, theme string) []byte {
	return MessagePageBytes("Not found", []byte("File not found: "+filename), theme)
}
<|endoftext|>


<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gateway

import (
	"sync"
	"time"

	pb "github.com/TheThingsNetwork/ttn/api/gateway"
	pb_router "github.com/TheThingsNetwork/ttn/api/router"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/apex/log"
)

// NewGateway creates a new in-memory Gateway structure
func NewGateway(ctx log.Interface, id string) *Gateway {
	ctx = ctx.WithField("GatewayID", id)
	return &Gateway{
		ID:          id,
		Status:      NewStatusStore(),
		Utilization: NewUtilization(),
		Schedule:    NewSchedule(ctx),
		Ctx:         ctx,
	}
}

// Gateway contains the state of a gateway
type Gateway struct {
	ID          string
	Status      StatusStore
	Utilization Utilization
	Schedule    Schedule
	LastSeen    time.Time

	Token     string
	tokenLock sync.Mutex

	monitor *monitorConn

	Ctx log.Interface
}

func (g *Gateway) SetToken(token string) {
	g.tokenLock.Lock()
	defer g.tokenLock.Unlock()

	g.Token = token
}

func (g *Gateway) updateTimestamp() {
	g.LastSeen = time.Now()
}

func (g *Gateway) HandleStatus(status *pb.Status) (err error) {
	if g.monitor != nil {
		go func() {
			cl, err := g.statusMonitor()
			if err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("Failed to establish status connection to the NOC")
			}

			if err = cl.Send(status); err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("NOC status push failed")
			}
		}()
	}

	g.updateTimestamp()
	return g.Status.Update(status)
}

func (g *Gateway) HandleUplink(uplink *pb_router.UplinkMessage) (err error) {
	if g.monitor != nil {
		go func() {
			cl, err := g.uplinkMonitor()
			if err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("Failed to establish uplink connection to the NOC")
			}

			if err = cl.Send(uplink); err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("NOC uplink push failed")
			}
		}()
	}

	g.updateTimestamp()
	g.Schedule.Sync(uplink.GatewayMetadata.Timestamp)
	return g.Utilization.AddRx(uplink)
}

func (g *Gateway) HandleDownlink(identifier string, downlink *pb_router.DownlinkMessage) (err error) {
	if g.monitor != nil {
		go func() {
			cl, err := g.downlinkMonitor()
			if err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("Failed to establish downlink connection to the NOC")
			}

			if err = cl.Send(downlink); err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("NOC downlink push failed")
			}
		}()
	}

	ctx := g.Ctx.WithField("Identifier", identifier)
	if err = g.Schedule.Schedule(identifier, downlink); err != nil {
		ctx.WithError(err).Warn("Could not schedule downlink")
	}
	return err
}
<commit_msg>core/router/gateway: push to NOC as last step<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gateway

import (
	"sync"
	"time"

	pb "github.com/TheThingsNetwork/ttn/api/gateway"
	pb_router "github.com/TheThingsNetwork/ttn/api/router"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/apex/log"
)

// NewGateway creates a new in-memory Gateway structure
func NewGateway(ctx log.Interface, id string) *Gateway {
	ctx = ctx.WithField("GatewayID", id)
	return &Gateway{
		ID:          id,
		Status:      NewStatusStore(),
		Utilization: NewUtilization(),
		Schedule:    NewSchedule(ctx),
		Ctx:         ctx,
	}
}

// Gateway contains the state of a gateway
type Gateway struct {
	ID          string
	Status      StatusStore
	Utilization Utilization
	Schedule    Schedule
	LastSeen    time.Time

	Token     string
	tokenLock sync.Mutex

	monitor *monitorConn

	Ctx log.Interface
}

func (g *Gateway) SetToken(token string) {
	g.tokenLock.Lock()
	defer g.tokenLock.Unlock()

	g.Token = token
}

func (g *Gateway) updateTimestamp() {
	g.LastSeen = time.Now()
}

func (g *Gateway) HandleStatus(status *pb.Status) (err error) {
	if err = g.Status.Update(status); err != nil {
		return err
	}
	g.updateTimestamp()

	if g.monitor != nil {
		go func() {
			cl, err := g.statusMonitor()
			if err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("Failed to establish status connection to the NOC")
			}

			if err = cl.Send(status); err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("NOC status push failed")
			}
		}()
	}
	return nil
}

func (g *Gateway) HandleUplink(uplink *pb_router.UplinkMessage) (err error) {
	if err = g.Utilization.AddRx(uplink); err != nil {
		return err
	}
	g.Schedule.Sync(uplink.GatewayMetadata.Timestamp)
	g.updateTimestamp()

	if g.monitor != nil {
		go func() {
			cl, err := g.uplinkMonitor()
			if err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("Failed to establish uplink connection to the NOC")
			}

			if err = cl.Send(uplink); err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("NOC uplink push failed")
			}
		}()
	}
	return nil
}

func (g *Gateway) HandleDownlink(identifier string, downlink *pb_router.DownlinkMessage) (err error) {
	ctx := g.Ctx.WithField("Identifier", identifier)
	if err = g.Schedule.Schedule(identifier, downlink); err != nil {
		ctx.WithError(err).Warn("Could not schedule downlink")
		return err
	}

	if g.monitor != nil {
		go func() {
			cl, err := g.downlinkMonitor()
			if err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("Failed to establish downlink connection to the NOC")
			}

			if err = cl.Send(downlink); err != nil {
				g.Ctx.WithError(errors.FromGRPCError(err)).Error("NOC downlink push failed")
			}
		}()
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gateway

import (
	"sync"
	"time"

	pb "github.com/TheThingsNetwork/ttn/api/gateway"
	pb_router "github.com/TheThingsNetwork/ttn/api/router"
	"github.com/apex/log"
)

// NewGateway creates a new in-memory Gateway structure
func NewGateway(ctx log.Interface, id string) *Gateway {
	ctx = ctx.WithField("GatewayID", id)
	return &Gateway{
		ID:          id,
		Status:      NewStatusStore(),
		Utilization: NewUtilization(),
		Schedule:    NewSchedule(ctx),
		Ctx:         ctx,
	}
}

// Gateway contains the state of a gateway
type Gateway struct {
	ID          string
	Status      StatusStore
	Utilization Utilization
	Schedule    Schedule
	LastSeen    time.Time

	Token     string
	tokenLock sync.Mutex

	monitor *monitorConn

	Ctx log.Interface
}

func (g *Gateway) SetToken(token string) {
	g.tokenLock.Lock()
	defer g.tokenLock.Unlock()

	g.Token = token
}

func (g *Gateway) updateLastSeen() {
	g.LastSeen = time.Now()
}

func (g *Gateway) HandleStatus(status *pb.Status) (err error) {
	if err = g.Status.Update(status); err != nil {
		return err
	}
	g.updateLastSeen()

	if g.monitor != nil {
		for name := range g.monitor.clients {
			go g.pushStatusToMonitor(g.Ctx.WithField("monitor", name), name, status)
		}
	}
	return nil
}

func (g *Gateway) HandleUplink(uplink *pb_router.UplinkMessage) (err error) {
	if err = g.Utilization.AddRx(uplink); err != nil {
		return err
	}
	g.Schedule.Sync(uplink.GatewayMetadata.Timestamp)
	g.updateLastSeen()

	if g.monitor != nil {
		for name := range g.monitor.clients {
			go g.pushUplinkToMonitor(g.Ctx.WithField("monitor", name), name, uplink)
		}
	}
	return nil
}

func (g *Gateway) HandleDownlink(identifier string, downlink *pb_router.DownlinkMessage) (err error) {
	ctx := g.Ctx.WithField("Identifier", identifier)
	if err = g.Schedule.Schedule(identifier, downlink); err != nil {
		ctx.WithError(err).Warn("Could not schedule downlink")
		return err
	}

	if g.monitor != nil {
		for name := range g.monitor.clients {
			go g.pushDownlinkToMonitor(ctx.WithField("monitor", name), name, downlink)
		}
	}
	return nil
}
<commit_msg>gateway monitor: capitalize log fields<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gateway

import (
	"sync"
	"time"

	pb "github.com/TheThingsNetwork/ttn/api/gateway"
	pb_router "github.com/TheThingsNetwork/ttn/api/router"
	"github.com/apex/log"
)

// NewGateway creates a new in-memory Gateway structure
func NewGateway(ctx log.Interface, id string) *Gateway {
	ctx = ctx.WithField("GatewayID", id)
	return &Gateway{
		ID:          id,
		Status:      NewStatusStore(),
		Utilization: NewUtilization(),
		Schedule:    NewSchedule(ctx),
		Ctx:         ctx,
	}
}

// Gateway contains the state of a gateway
type Gateway struct {
	ID          string
	Status      StatusStore
	Utilization Utilization
	Schedule    Schedule
	LastSeen    time.Time

	Token     string
	tokenLock sync.Mutex

	monitor *monitorConn

	Ctx log.Interface
}

func (g *Gateway) SetToken(token string) {
	g.tokenLock.Lock()
	defer g.tokenLock.Unlock()

	g.Token = token
}

func (g *Gateway) updateLastSeen() {
	g.LastSeen = time.Now()
}

func (g *Gateway) HandleStatus(status *pb.Status) (err error) {
	if err = g.Status.Update(status); err != nil {
		return err
	}
	g.updateLastSeen()

	if g.monitor != nil {
		for name := range g.monitor.clients {
			go g.pushStatusToMonitor(g.Ctx.WithField("Monitor", name), name, status)
		}
	}
	return nil
}

func (g *Gateway) HandleUplink(uplink *pb_router.UplinkMessage) (err error) {
	if err = g.Utilization.AddRx(uplink); err != nil {
		return err
	}
	g.Schedule.Sync(uplink.GatewayMetadata.Timestamp)
	g.updateLastSeen()

	if g.monitor != nil {
		for name := range g.monitor.clients {
			go g.pushUplinkToMonitor(g.Ctx.WithField("Monitor", name), name, uplink)
		}
	}
	return nil
}

func (g *Gateway) HandleDownlink(identifier string, downlink *pb_router.DownlinkMessage) (err error) {
	ctx := g.Ctx.WithField("Identifier", identifier)
	if err = g.Schedule.Schedule(identifier, downlink); err != nil {
		ctx.WithError(err).Warn("Could not schedule downlink")
		return err
	}

	if g.monitor != nil {
		for name := range g.monitor.clients {
			go g.pushDownlinkToMonitor(ctx.WithField("Monitor", name), name, downlink)
		}
	}
	return nil
}
<|endoftext|>