<commit_before>package golymer

import (
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/gopherjs/gopherjs/js"
)

func consoleError(args ...interface{}) {
	js.Global.Get("console").Call("error", args...)
}

//CustomElement the interface to create the CustomElement
type CustomElement interface {
	ConnectedCallback()
	DisconnectedCallback()
	AttributeChangedCallback(attributeName string, oldValue interface{}, newValue interface{}, namespace string)
	AdoptedCallback(oldDocument, newDocument interface{})
}

type oneWayDataBinding struct {
	Str       string
	Attribute *js.Object
	Paths     []attrPath
}

func (db oneWayDataBinding) SetAttr(obj *js.Object) {
	value := db.Str
	for _, path := range db.Paths {
		fieldValue := path.Get(obj).String()
		value = strings.Replace(value, "[["+path.String()+"]]", fieldValue, -1)
	}
	if db.Attribute.Get("value") != js.Undefined {
		db.Attribute.Set("value", value) //if it's an attribute
		return
	}
	db.Attribute.Set("data", value) //if it's an text node
}

type twoWayDataBinding struct {
	Attribute        *js.Object
	Path             attrPath
	MutationObserver *js.Object
}

func (db twoWayDataBinding) SetAttr(obj *js.Object) {
	value := db.Path.Get(obj)
	/*
		if timeValue, ok := value.Interface().(time.Time); ok {
			formatedTime := timeValue.Format(time.UnixDate)
			print(formatedTime)
			db.Attribute.Set("value", formatedTime)
			return
		}
	*/
	if db.Attribute.Get("value").String() != value.String() {
		db.Attribute.Set("value", value)
	}
}

//Element wrapper for the HTML element
type Element struct {
	*js.Object
	ObjValue           reflect.Value //custom element struct type
	Template           string
	Children           map[string]*js.Object
	oneWayDataBindings map[string][]*oneWayDataBinding
	twoWayDataBindings map[string]*twoWayDataBinding
}

//ConnectedCallback ...
func (e *Element) ConnectedCallback() {
	e.Call("attachShadow", map[string]interface{}{"mode": "open"})
	e.Get("shadowRoot").Set("innerHTML", e.Template)
	e.Children = make(map[string]*js.Object)
	e.oneWayDataBindings = make(map[string][]*oneWayDataBinding)
	e.twoWayDataBindings = make(map[string]*twoWayDataBinding)
	e.scanElement(e.Get("shadowRoot"))
}

//DisconnectedCallback ...
func (e *Element) DisconnectedCallback() {
}

//AttributeChangedCallback ...
func (e *Element) AttributeChangedCallback(attributeName string, oldValue interface{}, newValue interface{}, namespace string) {
	//if attribute didn't change don't set the field
	if oldValue != newValue {
		e.Get("__internal_object__").Set(toExportedFieldName(attributeName), newValue)
	}
}

//AdoptedCallback ...
func (e *Element) AdoptedCallback(oldDocument, newDocument interface{}) {
}

func (e *Element) scanElement(element *js.Object) {
	//find data binded attributes
	if elementAttributes := element.Get("attributes"); elementAttributes != js.Undefined {
		for i := 0; i < elementAttributes.Length(); i++ {
			attribute := elementAttributes.Index(i)
			//collect children with id
			if attribute.Get("name").String() == "id" {
				e.Children[attribute.Get("value").String()] = element
				continue
			}
			e.addOneWay(attribute, attribute.Get("value").String())
			e.addTwoWay(attribute, attribute.Get("value").String())
		}
	}
	//find textChild with data binded value
	childNodes := element.Get("childNodes")
	for i := 0; i < childNodes.Length(); i++ {
		child := childNodes.Index(i)
		if child.Get("nodeName").String() != "#text" {
			continue
		}
		e.addOneWay(child, child.Get("data").String())
	}
	//scan children
	children := element.Get("children")
	for i := 0; i < children.Length(); i++ {
		e.scanElement(children.Index(i))
	}
}

//addOneWay gets an js Attribute object or an textNode object and its text value
//than finds all data bindings and adds it to the oneWayDataBindings map
func (e *Element) addOneWay(obj *js.Object, value string) {
	var bindedPaths []attrPath
	for _, path := range oneWayFindAll(value) {
		bindedPaths = append(bindedPaths, newAttrPath(path))
	}
	for _, bindedPath := range bindedPaths {
		e.subpropertyProxySet(bindedPath)
		db := &oneWayDataBinding{Str: value, Attribute: obj, Paths: bindedPaths}
		e.oneWayDataBindings[bindedPath.String()] = append(e.oneWayDataBindings[bindedPath.String()], db)
		db.SetAttr(e.Object)
	}
}

//addTwoWay gets an js Attribute object or an textNode object and its text value
//than finds all data bindings and adds it to the twoWayDataBindings map
func (e *Element) addTwoWay(obj *js.Object, value string) {
	//twoWayDataBinding, obj is attribute DOM object and value is in {{}}
	if obj.Get("value") == js.Undefined || value[:2] != "{{" || value[len(value)-2:] != "}}" {
		return
	}
	path := newAttrPath(value[2 : len(value)-2])
	if _, ok := e.twoWayDataBindings[path.String()]; ok {
		consoleError("data binding", path.String(), "set more than once")
	}
	e.subpropertyProxySet(path)
	mutationObserver := newMutationObserver(e.Get("__internal_object__"), obj, path)
	db := &twoWayDataBinding{Attribute: obj, Path: path, MutationObserver: mutationObserver}
	e.twoWayDataBindings[path.String()] = db
	db.SetAttr(e.Object)
}

//subpropertyProxySet sets an js Proxy on an subproperty path to track get and set on its properties
func (e *Element) subpropertyProxySet(bindedPath attrPath) {
	subpropertyPath := bindedPath[:len(bindedPath)-1]
	if len(subpropertyPath) > 0 && !e.subpropertyProxyAdded(subpropertyPath) {
		proxy := newProxy(e.ObjValue, subpropertyPath)
		subpropertyPath.Set(js.InternalObject(e.ObjValue).Get("ptr"), proxy)
	}
}

func (e *Element) subpropertyProxyAdded(subpropertyPath attrPath) bool {
	for p := range e.oneWayDataBindings {
		subPath := newAttrPath(p)
		subPath = subPath[:len(subPath)-1]
		if subPath.String() == subpropertyPath.String() {
			return true
		}
	}
	for p := range e.twoWayDataBindings {
		subPath := newAttrPath(p)
		subPath = subPath[:len(subPath)-1]
		if subPath.String() == subpropertyPath.String() {
			return true
		}
	}
	return false
}

func newMutationObserver(proxy *js.Object, attr *js.Object, path attrPath) *js.Object {
	attr.Set("__attr_path__", path.String())
	mutationObserver := js.Global.Get("window").Get("MutationObserver").New(
		js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			newValue := attr.Get("value")
			path := newAttrPath(attr.Get("__attr_path__").String())
			if path.Get(proxy) != newValue {
				path.Set(proxy, newValue)
			}
			return nil
		}))
	mutationObserver.Call(
		"observe",
		attr.Get("ownerElement"),
		map[string]interface{}{
			"attributes":      true,
			"attributeFilter": []string{attr.Get("name").String()},
		},
	)
	return mutationObserver
}

//newProxy creates an js Proxy object that can track what has been get or set to run dataBindings
func newProxy(customObject reflect.Value, pathPrefix attrPath) (proxy *js.Object) {
	internalCustomObject := js.InternalObject(customObject.Interface())
	subObj := internalCustomObject
	if len(pathPrefix) > 0 {
		subObj = pathPrefix.Get(subObj)
	}
	handler := map[string]interface{}{
		"get": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			attributeName := arguments[1].String()
			if attributeName == "__internal_object__" || attributeName == "$val" {
				return proxy
			}
			return subObj.Get(attributeName)
		}),
		"set": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			attributeName := arguments[1].String()
			path := append(pathPrefix, attributeName)
			field, ok := path.GetField(customObject.Elem().Type())
			//field doesn't exist
			if !ok {
				return true
			}
			if isDataBindingExpression(arguments[2]) {
				return true
			}
			convertedValue, err := convertJSType(field.Type, arguments[2])
			if err != nil {
				consoleError(
					"Error converting value in setting the property",
					path.String(),
					": (", arguments[2], ")",
					err,
				)
				return true
			}
			subObj.Set(attributeName, convertedValue)
			//if it's exported and isn't a subproperty set also the tag attribute
			if len(pathPrefix) == 0 && field.PkgPath == "" {
				instance := subObj.Get("Element").Get("Object")
				instance.Call("setAttribute", camelCaseToKebab(attributeName), arguments[2])
			}
			//sets binded attributes of the children in template
			elem := customObject.Elem().FieldByName("Element").Interface().(Element)
			if dbs, ok := elem.oneWayDataBindings[path.String()]; ok {
				for _, db := range dbs {
					db.SetAttr(internalCustomObject)
				}
			}
			if db, ok := elem.twoWayDataBindings[path.String()]; ok {
				db.SetAttr(internalCustomObject)
			}
			return true
		}),
	}
	proxy = js.Global.Get("Proxy").New(subObj, handler)
	return
}

func convertJSType(t reflect.Type, value *js.Object) (val interface{}, err error) {
	val = value.Interface()
	valString, ok := val.(string)
	if !ok {
		return
	}
	switch t.Kind() {
	case reflect.String:
		val = valString
		return
	case reflect.Bool:
		val, err = strconv.ParseBool(valString)
	case reflect.Float32:
		val, err = strconv.ParseFloat(valString, 32)
	case reflect.Float64:
		val, err = strconv.ParseFloat(valString, 64)
	case reflect.Int:
		val, err = strconv.ParseInt(valString, 10, 64)
	case reflect.Int16:
		val, err = strconv.ParseInt(valString, 10, 16)
	case reflect.Int32:
		val, err = strconv.ParseInt(valString, 10, 32)
	case reflect.Int64:
		val, err = strconv.ParseInt(valString, 10, 64)
	case reflect.Uint:
		val, err = strconv.ParseUint(valString, 10, 64)
	case reflect.Uint16:
		val, err = strconv.ParseUint(valString, 10, 16)
	case reflect.Uint32:
		val, err = strconv.ParseUint(valString, 10, 32)
	case reflect.Uint64:
		val, err = strconv.ParseUint(valString, 10, 64)
	case reflect.Struct:
		if t.Name() == "Time" {
			val, err = time.Parse(time.UnixDate, valString)
			return
		}
	}
	return
}

func isDataBindingExpression(val *js.Object) bool {
	valString, ok := val.Interface().(string)
	if !ok {
		return false
	}
	if len(valString) < 4 {
		return false
	}
	return (valString[:2] == "{{" && valString[len(valString)-2:] == "}}") ||
		(valString[:2] == "||" && valString[len(valString)-2:] == "||")
}
<commit_msg>addEventListener<commit_after>package golymer

import (
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/gopherjs/gopherjs/js"
)

func consoleError(args ...interface{}) {
	js.Global.Get("console").Call("error", args...)
}

//CustomElement the interface to create the CustomElement
type CustomElement interface {
	ConnectedCallback()
	DisconnectedCallback()
	AttributeChangedCallback(attributeName string, oldValue interface{}, newValue interface{}, namespace string)
	AdoptedCallback(oldDocument, newDocument interface{})
}

type oneWayDataBinding struct {
	Str       string
	Attribute *js.Object
	Paths     []attrPath
}

func (db oneWayDataBinding) SetAttr(obj *js.Object) {
	value := db.Str
	for _, path := range db.Paths {
		fieldValue := path.Get(obj).String()
		value = strings.Replace(value, "[["+path.String()+"]]", fieldValue, -1)
	}
	if db.Attribute.Get("value") != js.Undefined {
		db.Attribute.Set("value", value) //if it's an attribute
		return
	}
	db.Attribute.Set("data", value) //if it's an text node
}

type twoWayDataBinding struct {
	Attribute        *js.Object
	Path             attrPath
	MutationObserver *js.Object
}

func (db twoWayDataBinding) SetAttr(obj *js.Object) {
	value := db.Path.Get(obj)
	/*
		if timeValue, ok := value.Interface().(time.Time); ok {
			formatedTime := timeValue.Format(time.UnixDate)
			print(formatedTime)
			db.Attribute.Set("value", formatedTime)
			return
		}
	*/
	if db.Attribute.Get("value").String() != value.String() {
		db.Attribute.Set("value", value)
	}
}

//Element wrapper for the HTML element
type Element struct {
	*js.Object
	ObjValue           reflect.Value //custom element struct type
	Template           string
	Children           map[string]*js.Object
	oneWayDataBindings map[string][]*oneWayDataBinding
	twoWayDataBindings map[string]*twoWayDataBinding
}

//ConnectedCallback ...
func (e *Element) ConnectedCallback() {
	e.Call("attachShadow", map[string]interface{}{"mode": "open"})
	e.Get("shadowRoot").Set("innerHTML", e.Template)
	e.Children = make(map[string]*js.Object)
	e.oneWayDataBindings = make(map[string][]*oneWayDataBinding)
	e.twoWayDataBindings = make(map[string]*twoWayDataBinding)
	e.scanElement(e.Get("shadowRoot"))
}

//DisconnectedCallback ...
func (e *Element) DisconnectedCallback() {
}

//AttributeChangedCallback ...
func (e *Element) AttributeChangedCallback(attributeName string, oldValue interface{}, newValue interface{}, namespace string) {
	//if attribute didn't change don't set the field
	if oldValue != newValue {
		e.Get("__internal_object__").Set(toExportedFieldName(attributeName), newValue)
	}
}

//AdoptedCallback ...
func (e *Element) AdoptedCallback(oldDocument, newDocument interface{}) {
}

func (e *Element) scanElement(element *js.Object) {
	//find data binded attributes
	if elementAttributes := element.Get("attributes"); elementAttributes != js.Undefined {
		for i := 0; i < elementAttributes.Length(); i++ {
			attribute := elementAttributes.Index(i)
			//collect children with id
			if attribute.Get("name").String() == "id" {
				e.Children[attribute.Get("value").String()] = element
				continue
			}
			e.addOneWay(attribute, attribute.Get("value").String())
			e.addTwoWay(attribute, attribute.Get("value").String())
			if attribute.Get("name").String()[:3] == "on-" {
				e.addEventListener(attribute)
			}
		}
	}
	//find textChild with data binded value
	childNodes := element.Get("childNodes")
	for i := 0; i < childNodes.Length(); i++ {
		child := childNodes.Index(i)
		if child.Get("nodeName").String() != "#text" {
			continue
		}
		e.addOneWay(child, child.Get("data").String())
	}
	//scan children
	children := element.Get("children")
	for i := 0; i < children.Length(); i++ {
		e.scanElement(children.Index(i))
	}
}

//addOneWay gets an js Attribute object or an textNode object and its text value
//than finds all data bindings and adds it to the oneWayDataBindings map
func (e *Element) addOneWay(obj *js.Object, value string) {
	var bindedPaths []attrPath
	for _, path := range oneWayFindAll(value) {
		bindedPaths = append(bindedPaths, newAttrPath(path))
	}
	for _, bindedPath := range bindedPaths {
		e.subpropertyProxySet(bindedPath)
		db := &oneWayDataBinding{Str: value, Attribute: obj, Paths: bindedPaths}
		e.oneWayDataBindings[bindedPath.String()] = append(e.oneWayDataBindings[bindedPath.String()], db)
		db.SetAttr(e.Object)
	}
}

//addTwoWay gets an js Attribute object or an textNode object and its text value
//than finds all data bindings and adds it to the twoWayDataBindings map
func (e *Element) addTwoWay(obj *js.Object, value string) {
	//twoWayDataBinding, obj is attribute DOM object and value is in {{}}
	if obj.Get("value") == js.Undefined || value[:2] != "{{" || value[len(value)-2:] != "}}" {
		return
	}
	path := newAttrPath(value[2 : len(value)-2])
	if _, ok := e.twoWayDataBindings[path.String()]; ok {
		consoleError("data binding", path.String(), "set more than once")
	}
	e.subpropertyProxySet(path)
	mutationObserver := newMutationObserver(e.Get("__internal_object__"), obj, path)
	db := &twoWayDataBinding{Attribute: obj, Path: path, MutationObserver: mutationObserver}
	e.twoWayDataBindings[path.String()] = db
	db.SetAttr(e.Object)
}

func (e *Element) addEventListener(attr *js.Object) {
	eventName := attr.Get("name").String()[3:]
	methodName := attr.Get("value").String()
	method := e.ObjValue.MethodByName(methodName)
	if !method.IsValid() {
		consoleError("Error on event listener binding, method", methodName, "doesn't exist")
		return
	}
	e.Call("addEventListener", eventName, js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
		var in []reflect.Value
		for _, arg := range arguments {
			in = append(in, reflect.ValueOf(arg.Interface()))
		}
		method.Call(in)
		return nil
	}))
}

//subpropertyProxySet sets an js Proxy on an subproperty path to track get and set on its properties
func (e *Element) subpropertyProxySet(bindedPath attrPath) {
	subpropertyPath := bindedPath[:len(bindedPath)-1]
	if len(subpropertyPath) > 0 && !e.subpropertyProxyAdded(subpropertyPath) {
		proxy := newProxy(e.ObjValue, subpropertyPath)
		subpropertyPath.Set(js.InternalObject(e.ObjValue).Get("ptr"), proxy)
	}
}

func (e *Element) subpropertyProxyAdded(subpropertyPath attrPath) bool {
	for p := range e.oneWayDataBindings {
		subPath := newAttrPath(p)
		subPath = subPath[:len(subPath)-1]
		if subPath.String() == subpropertyPath.String() {
			return true
		}
	}
	for p := range e.twoWayDataBindings {
		subPath := newAttrPath(p)
		subPath = subPath[:len(subPath)-1]
		if subPath.String() == subpropertyPath.String() {
			return true
		}
	}
	return false
}

func newMutationObserver(proxy *js.Object, attr *js.Object, path attrPath) *js.Object {
	attr.Set("__attr_path__", path.String())
	mutationObserver := js.Global.Get("window").Get("MutationObserver").New(
		js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			newValue := attr.Get("value")
			path := newAttrPath(attr.Get("__attr_path__").String())
			if path.Get(proxy) != newValue {
				path.Set(proxy, newValue)
			}
			return nil
		}))
	mutationObserver.Call(
		"observe",
		attr.Get("ownerElement"),
		map[string]interface{}{
			"attributes":      true,
			"attributeFilter": []string{attr.Get("name").String()},
		},
	)
	return mutationObserver
}

//newProxy creates an js Proxy object that can track what has been get or set to run dataBindings
func newProxy(customObject reflect.Value, pathPrefix attrPath) (proxy *js.Object) {
	internalCustomObject := js.InternalObject(customObject.Interface())
	subObj := internalCustomObject
	if len(pathPrefix) > 0 {
		subObj = pathPrefix.Get(subObj)
	}
	handler := map[string]interface{}{
		"get": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			attributeName := arguments[1].String()
			if attributeName == "__internal_object__" || attributeName == "$val" {
				return proxy
			}
			return subObj.Get(attributeName)
		}),
		"set": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			attributeName := arguments[1].String()
			path := append(pathPrefix, attributeName)
			field, ok := path.GetField(customObject.Elem().Type())
			//field doesn't exist
			if !ok {
				return true
			}
			if isDataBindingExpression(arguments[2]) {
				return true
			}
			convertedValue, err := convertJSType(field.Type, arguments[2])
			if err != nil {
				consoleError(
					"Error converting value in setting the property",
					path.String(),
					": (", arguments[2], ")",
					err,
				)
				return true
			}
			subObj.Set(attributeName, convertedValue)
			//if it's exported and isn't a subproperty set also the tag attribute
			if len(pathPrefix) == 0 && field.PkgPath == "" {
				instance := subObj.Get("Element").Get("Object")
				instance.Call("setAttribute", camelCaseToKebab(attributeName), arguments[2])
			}
			//sets binded attributes of the children in template
			elem := customObject.Elem().FieldByName("Element").Interface().(Element)
			if dbs, ok := elem.oneWayDataBindings[path.String()]; ok {
				for _, db := range dbs {
					db.SetAttr(internalCustomObject)
				}
			}
			if db, ok := elem.twoWayDataBindings[path.String()]; ok {
				db.SetAttr(internalCustomObject)
			}
			return true
		}),
	}
	proxy = js.Global.Get("Proxy").New(subObj, handler)
	return
}

func convertJSType(t reflect.Type, value *js.Object) (val interface{}, err error) {
	val = value.Interface()
	valString, ok := val.(string)
	if !ok {
		return
	}
	switch t.Kind() {
	case reflect.String:
		val = valString
		return
	case reflect.Bool:
		val, err = strconv.ParseBool(valString)
	case reflect.Float32:
		val, err = strconv.ParseFloat(valString, 32)
	case reflect.Float64:
		val, err = strconv.ParseFloat(valString, 64)
	case reflect.Int:
		val, err = strconv.ParseInt(valString, 10, 64)
	case reflect.Int16:
		val, err = strconv.ParseInt(valString, 10, 16)
	case reflect.Int32:
		val, err = strconv.ParseInt(valString, 10, 32)
	case reflect.Int64:
		val, err = strconv.ParseInt(valString, 10, 64)
	case reflect.Uint:
		val, err = strconv.ParseUint(valString, 10, 64)
	case reflect.Uint16:
		val, err = strconv.ParseUint(valString, 10, 16)
	case reflect.Uint32:
		val, err = strconv.ParseUint(valString, 10, 32)
	case reflect.Uint64:
		val, err = strconv.ParseUint(valString, 10, 64)
	case reflect.Struct:
		if t.Name() == "Time" {
			val, err = time.Parse(time.UnixDate, valString)
			return
		}
	}
	return
}

func isDataBindingExpression(val *js.Object) bool {
	valString, ok := val.Interface().(string)
	if !ok {
		return false
	}
	if len(valString) < 4 {
		return false
	}
	return (valString[:2] == "{{" && valString[len(valString)-2:] == "}}") ||
		(valString[:2] == "||" && valString[len(valString)-2:] == "||")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/hashicorp/raft"
	"github.com/robustirc/robustirc/config"
	"github.com/robustirc/robustirc/ircserver"
	"github.com/robustirc/robustirc/raft_store"
	"github.com/robustirc/robustirc/types"
	"github.com/sorcix/irc"
	"github.com/stapelberg/glog"
)

type FSM struct {
	// Used for invalidating messages of death.
	store *raft_store.LevelDBStore

	ircstore *raft_store.LevelDBStore
}

func (fsm *FSM) Apply(l *raft.Log) interface{} {
	// Skip all messages that are raft-related.
	if l.Type != raft.LogCommand {
		return nil
	}

	if err := fsm.ircstore.StoreLog(l); err != nil {
		log.Panicf("Could not persist message in irclogs/: %v", err)
	}

	msg := types.NewRobustMessageFromBytes(l.Data)
	log.Printf("Apply(msg.Type=%s)\n", msg.Type)

	defer func() {
		if msg.Type == types.RobustMessageOfDeath {
			return
		}
		if r := recover(); r != nil {
			// Panics in ircserver.ProcessMessage() are a problem, since
			// they will bring down the entire raft cluster and you cannot
			// bring up any raft node anymore without deleting the entire
			// log.
			//
			// Therefore, when we panic, we invalidate the log entry in
			// question before crashing. This doesn’t fix the underlying
			// bug, i.e. an IRC message will then go unhandled, but it
			// prevents RobustIRC from dying horribly in such a situation.
			msg.Type = types.RobustMessageOfDeath
			data, err := json.Marshal(msg)
			if err != nil {
				glog.Fatalf("Could not marshal message: %v", err)
			}
			l.Data = data
			if err := fsm.store.StoreLog(l); err != nil {
				glog.Fatalf("Could not store log while marking message as message of death: %v", err)
			}
			log.Printf("Marked %+v as message of death\n", l)
			glog.Fatalf("%v", r)
		}
	}()

	switch msg.Type {
	case types.RobustMessageOfDeath:
		// To prevent the message from being accepted again.
		ircServer.UpdateLastClientMessageID(&msg)
		log.Printf("Skipped message of death.\n")

	case types.RobustCreateSession:
		ircServer.CreateSession(msg.Id, msg.Data)

	case types.RobustDeleteSession:
		if _, err := ircServer.GetSession(msg.Session); err == nil {
			// TODO(secure): overwrite QUIT messages for services with an faq entry explaining that they are not robust yet.
			reply := ircServer.ProcessMessage(msg.Id, msg.Session, irc.ParseMessage("QUIT :"+string(msg.Data)))
			ircServer.SendMessages(reply, msg.Session, msg.Id.Id)
		}

	case types.RobustIRCFromClient:
		// Need to do this first, because ircserver.ProcessMessage could delete
		// the session, e.g. by using KILL or QUIT.
		if err := ircServer.UpdateLastClientMessageID(&msg); err != nil {
			log.Printf("Error updating the last message for session: %v\n", err)
		} else {
			reply := ircServer.ProcessMessage(msg.Id, msg.Session, irc.ParseMessage(string(msg.Data)))
			ircServer.SendMessages(reply, msg.Session, msg.Id.Id)
		}

	case types.RobustConfig:
		newCfg, err := config.FromString(string(msg.Data))
		if err != nil {
			log.Printf("Skipping unexpectedly invalid configuration (%v)\n", err)
		} else {
			netConfig = newCfg
			ircServer.Config = netConfig.IRC
		}
	}

	appliedMessages.WithLabelValues(msg.Type.String()).Inc()

	return nil
}

// Snapshot returns a list of pointers based on which a snapshot can be
// created. After restoring that snapshot, the server state (current sessions,
// channels, modes, …) should be identical to the state before taking the
// snapshot. Note that entries are compacted, i.e. useless state
// transformations (think multiple nickname changes) are skipped. Also note
// that the IRC output is not guaranteed to end up the same as before. This is
// not a problem in practice as only log entries which are older than a couple
// of days are compacted, and proxy connections are only disconnected for a
// couple of minutes at a time.
func (fsm *FSM) Snapshot() (raft.FSMSnapshot, error) {
	first, err := fsm.ircstore.FirstIndex()
	if err != nil {
		return nil, err
	}

	last, err := fsm.ircstore.LastIndex()
	if err != nil {
		return nil, err
	}

	return &robustSnapshot{
		firstIndex: first,
		lastIndex:  last,
		store:      fsm.ircstore,
		del:        make(map[uint64]types.RobustId),
		servers:    make(map[int64]bool),
		idToIdx:    make(map[int64]uint64),
	}, err
}

func (fsm *FSM) Restore(snap io.ReadCloser) error {
	log.Printf("Restoring snapshot\n")
	defer snap.Close()

	if err := fsm.ircstore.Close(); err != nil {
		log.Fatal(err)
	}
	// Deleting irclog and creating a new database is significantly faster than
	// using DeleteRange() on the entire keyspace. Re-creating the database
	// saves us 4 minutes of CPU time (out of 5 minutes total!) and >1G of
	// memory usage.
	irclogPath := filepath.Join(*raftDir, "irclog")
	if err := os.RemoveAll(irclogPath); err != nil {
		log.Fatal(err)
	}
	var err error
	ircStore, err = raft_store.NewLevelDBStore(irclogPath, true)
	if err != nil {
		log.Fatal(err)
	}
	fsm.ircstore = ircStore

	ircServer = ircserver.NewIRCServer(*raftDir, *network, time.Now())

	decoder := json.NewDecoder(snap)
	for {
		var entry raft.Log
		if err := decoder.Decode(&entry); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		// TODO(secure): is it okay to re-apply these entries? i.e., when
		// restoring snapshots during normal operation (when does that
		// happen?), will we re-send messages to clients?
		fsm.Apply(&entry)
	}

	log.Printf("Restored snapshot\n")

	return nil
}
<commit_msg>statemachine: remove obsolete comment<commit_after>package main

import (
	"encoding/json"
	"io"
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/hashicorp/raft"
	"github.com/robustirc/robustirc/config"
	"github.com/robustirc/robustirc/ircserver"
	"github.com/robustirc/robustirc/raft_store"
	"github.com/robustirc/robustirc/types"
	"github.com/sorcix/irc"
	"github.com/stapelberg/glog"
)

type FSM struct {
	// Used for invalidating messages of death.
	store *raft_store.LevelDBStore

	ircstore *raft_store.LevelDBStore
}

func (fsm *FSM) Apply(l *raft.Log) interface{} {
	// Skip all messages that are raft-related.
	if l.Type != raft.LogCommand {
		return nil
	}

	if err := fsm.ircstore.StoreLog(l); err != nil {
		log.Panicf("Could not persist message in irclogs/: %v", err)
	}

	msg := types.NewRobustMessageFromBytes(l.Data)
	log.Printf("Apply(msg.Type=%s)\n", msg.Type)

	defer func() {
		if msg.Type == types.RobustMessageOfDeath {
			return
		}
		if r := recover(); r != nil {
			// Panics in ircserver.ProcessMessage() are a problem, since
			// they will bring down the entire raft cluster and you cannot
			// bring up any raft node anymore without deleting the entire
			// log.
			//
			// Therefore, when we panic, we invalidate the log entry in
			// question before crashing. This doesn’t fix the underlying
			// bug, i.e. an IRC message will then go unhandled, but it
			// prevents RobustIRC from dying horribly in such a situation.
			msg.Type = types.RobustMessageOfDeath
			data, err := json.Marshal(msg)
			if err != nil {
				glog.Fatalf("Could not marshal message: %v", err)
			}
			l.Data = data
			if err := fsm.store.StoreLog(l); err != nil {
				glog.Fatalf("Could not store log while marking message as message of death: %v", err)
			}
			log.Printf("Marked %+v as message of death\n", l)
			glog.Fatalf("%v", r)
		}
	}()

	switch msg.Type {
	case types.RobustMessageOfDeath:
		// To prevent the message from being accepted again.
		ircServer.UpdateLastClientMessageID(&msg)
		log.Printf("Skipped message of death.\n")

	case types.RobustCreateSession:
		ircServer.CreateSession(msg.Id, msg.Data)

	case types.RobustDeleteSession:
		if _, err := ircServer.GetSession(msg.Session); err == nil {
			// TODO(secure): overwrite QUIT messages for services with an faq entry explaining that they are not robust yet.
			reply := ircServer.ProcessMessage(msg.Id, msg.Session, irc.ParseMessage("QUIT :"+string(msg.Data)))
			ircServer.SendMessages(reply, msg.Session, msg.Id.Id)
		}

	case types.RobustIRCFromClient:
		// Need to do this first, because ircserver.ProcessMessage could delete
		// the session, e.g. by using KILL or QUIT.
		if err := ircServer.UpdateLastClientMessageID(&msg); err != nil {
			log.Printf("Error updating the last message for session: %v\n", err)
		} else {
			reply := ircServer.ProcessMessage(msg.Id, msg.Session, irc.ParseMessage(string(msg.Data)))
			ircServer.SendMessages(reply, msg.Session, msg.Id.Id)
		}

	case types.RobustConfig:
		newCfg, err := config.FromString(string(msg.Data))
		if err != nil {
			log.Printf("Skipping unexpectedly invalid configuration (%v)\n", err)
		} else {
			netConfig = newCfg
			ircServer.Config = netConfig.IRC
		}
	}

	appliedMessages.WithLabelValues(msg.Type.String()).Inc()

	return nil
}

// Snapshot returns a list of pointers based on which a snapshot can be
// created. After restoring that snapshot, the server state (current sessions,
// channels, modes, …) should be identical to the state before taking the
// snapshot. Note that entries are compacted, i.e. useless state
// transformations (think multiple nickname changes) are skipped. Also note
// that the IRC output is not guaranteed to end up the same as before. This is
// not a problem in practice as only log entries which are older than a couple
// of days are compacted, and proxy connections are only disconnected for a
// couple of minutes at a time.
func (fsm *FSM) Snapshot() (raft.FSMSnapshot, error) {
	first, err := fsm.ircstore.FirstIndex()
	if err != nil {
		return nil, err
	}

	last, err := fsm.ircstore.LastIndex()
	if err != nil {
		return nil, err
	}

	return &robustSnapshot{
		firstIndex: first,
		lastIndex:  last,
		store:      fsm.ircstore,
		del:        make(map[uint64]types.RobustId),
		servers:    make(map[int64]bool),
		idToIdx:    make(map[int64]uint64),
	}, err
}

func (fsm *FSM) Restore(snap io.ReadCloser) error {
	log.Printf("Restoring snapshot\n")
	defer snap.Close()

	if err := fsm.ircstore.Close(); err != nil {
		log.Fatal(err)
	}
	// Deleting irclog and creating a new database is significantly faster than
	// using DeleteRange() on the entire keyspace. Re-creating the database
	// saves us 4 minutes of CPU time (out of 5 minutes total!) and >1G of
	// memory usage.
	irclogPath := filepath.Join(*raftDir, "irclog")
	if err := os.RemoveAll(irclogPath); err != nil {
		log.Fatal(err)
	}
	var err error
	ircStore, err = raft_store.NewLevelDBStore(irclogPath, true)
	if err != nil {
		log.Fatal(err)
	}
	fsm.ircstore = ircStore

	ircServer = ircserver.NewIRCServer(*raftDir, *network, time.Now())

	decoder := json.NewDecoder(snap)
	for {
		var entry raft.Log
		if err := decoder.Decode(&entry); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		fsm.Apply(&entry)
	}

	log.Printf("Restored snapshot\n")

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"

	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

type Config struct {
	Region       string `mapstructure:"region"`
	Bucket       string `mapstructure:"bucket"`
	ManifestPath string `mapstructure:"manifest"`
	BoxName      string `mapstructure:"box_name"`
	BoxDir       string `mapstructure:"box_dir"`
	Version      string `mapstructure:"version"`
	ACL          s3.ACL `mapstructure:"acl"`
	AccessKey    string `mapstructure:"access_key_id"`
	SecretKey    string `mapstructure:"secret_key"`
	common.PackerConfig    `mapstructure:",squash"`

	ctx          interpolate.Context
}

type PostProcessor struct {
	config Config
	s3     *s3.Bucket
}

func (p *PostProcessor) Configure(raws ...interface{}) error {
	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{"output"},
		},
	}, raws...)
	if err != nil {
		return err
	}

	errs := new(packer.MultiError)
	// required configuration
	templates := map[string]*string{
		"region":   &p.config.Region,
		"bucket":   &p.config.Bucket,
		"manifest": &p.config.ManifestPath,
		"box_name": &p.config.BoxName,
		"box_dir":  &p.config.BoxDir,
		"version":  &p.config.Version,
	}

	for key, ptr := range templates {
		if *ptr == "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("vagrant-s3 %s must be set", key))
		}
	}

	// Template process
	for key, ptr := range templates {
		if err = interpolate.Validate(*ptr, &p.config.ctx); err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error parsing %s template: %s", key, err))
		}
	}

	auth, err := aws.GetAuth(p.config.AccessKey, p.config.SecretKey)
	if err != nil {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Unable to create Aws Authentication. Try providing keys 'access_key_id' and 'secret_key'"))
	}

	// determine region
	region, valid := aws.Regions[p.config.Region]
	if valid {
		p.s3 = s3.New(auth, region).Bucket(p.config.Bucket)
	} else {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Invalid region specified: %s", p.config.Region))
	}

	if p.config.ACL == "" {
		p.config.ACL = "public-read"
	}

	if len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	// Only accept input from the vagrant post-processor
	if artifact.BuilderId() != "mitchellh.post-processor.vagrant" {
		return nil, false, fmt.Errorf("Unknown artifact type, requires box from vagrant post-processor: %s", artifact.BuilderId())
	}

	// Assume there is only one .box file to upload
	box := artifact.Files()[0]
	if !strings.HasSuffix(box, ".box") {
		return nil, false, fmt.Errorf("Unknown files in artifact from vagrant post-processor: %s", artifact.Files())
	}

	provider := providerFromBuilderName(artifact.Id())
	ui.Say(fmt.Sprintf("Preparing to upload box for '%s' provider to S3 bucket '%s'", provider, p.config.Bucket))

	// open the box so we can upload to S3 and calculate checksum for the manifest
	file, err := os.Open(box)
	if err != nil {
		return nil, false, err
	}
	defer file.Close()

	// get the file's size
	info, err := file.Stat()
	if err != nil {
		return nil, false, err
	}
	size := info.Size()
	ui.Message(fmt.Sprintf("Box to upload: %s (%d bytes)", box, size))

	// get the latest manifest so we can add to it
	ui.Message("Fetching latest manifest")
	manifest, err := p.getManifest()
	if err != nil {
		return nil, false, err
	}

	// generate the path to store the box in S3
	boxPath := fmt.Sprintf("%s/%s/%s", p.config.BoxDir, p.config.Version, path.Base(box))

	ui.Message("Generating checksum")
	checksum, err := sum256(file)
	if err != nil {
		return nil, false, err
	}
	ui.Message(fmt.Sprintf("Checksum is %s", checksum))

	ui.Message(fmt.Sprintf("Adding %s %s box to manifest", provider, p.config.Version))
	if err := manifest.add(p.config.Version, &Provider{
		Name:         provider,
		Url:          p.s3.URL(boxPath),
		ChecksumType: "sha256",
		Checksum:     checksum,
	}); err != nil {
		return nil, false, err
	}

	// upload the box to S3 (rewinding as we already read the file to generate the checksum)
	ui.Message(fmt.Sprintf("Uploading box to S3: %s", boxPath))
	if _, err := file.Seek(0, 0); err != nil {
		return nil, false, err
	}
	if size > 100*1024*1024 {
		ui.Message("File size > 100MB. Initiating multipart upload")
		multi, err := p.s3.Multi(boxPath, "application/octet-stream", p.config.ACL)
		if err != nil {
			return nil, false, err
		}
		parts, err := multi.PutAll(file, 5*1024*1024)
		if err != nil {
			return nil, false, err
		}
		if err := multi.Complete(parts); err != nil {
			return nil, false, err
		}
	} else {
		if err := p.s3.PutReader(boxPath, file, size, "application/octet-stream", p.config.ACL); err != nil {
			return nil, false, err
		}
	}

	ui.Message(fmt.Sprintf("Uploading the manifest: %s", p.config.ManifestPath))
	if err := p.putManifest(manifest); err != nil {
		return nil, false, err
	}

	return &Artifact{p.s3.URL(p.config.ManifestPath)}, true, nil
}

func (p *PostProcessor) getManifest() (*Manifest, error) {
	body, err := p.s3.GetReader(p.config.ManifestPath)
	if err != nil {
		s3Err, ok := err.(*s3.Error);
		if  ok && s3Err.Code == "NoSuchKey" {
			return &Manifest{Name: p.config.BoxName}, nil
		}
		return nil, err
	}
	defer body.Close()

	manifest := &Manifest{}
	if err := json.NewDecoder(body).Decode(manifest); err != nil {
		return nil, err
	}
	return manifest, nil
}

func (p *PostProcessor) putManifest(manifest *Manifest) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(manifest); err != nil {
		return err
	}
	if err := p.s3.Put(p.config.ManifestPath, buf.Bytes(), "application/json", p.config.ACL); err != nil {
		return err
	}
	return nil
}

// calculates a sha256 checksum of the file
func sum256(file *os.File) (string, error) {
	h := sha256.New()
	if _, err := io.Copy(h, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(h.Sum(nil)), nil
}

// converts a packer builder name to the corresponding vagrant provider
func providerFromBuilderName(name string) string {
	switch name {
	case "aws":
		return "aws"
	case "digitalocean":
		return "digitalocean"
	case "virtualbox":
		return "virtualbox"
	case "vmware":
		return "vmware_desktop"
	case "parallels":
		return "parallels"
	default:
		return name
	}
}
<commit_msg>gofmt<commit_after>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"

	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

type Config struct {
	Region              string `mapstructure:"region"`
	Bucket              string `mapstructure:"bucket"`
	ManifestPath        string `mapstructure:"manifest"`
	BoxName             string `mapstructure:"box_name"`
	BoxDir              string `mapstructure:"box_dir"`
	Version             string `mapstructure:"version"`
	ACL                 s3.ACL `mapstructure:"acl"`
	AccessKey           string `mapstructure:"access_key_id"`
	SecretKey           string `mapstructure:"secret_key"`
	common.PackerConfig `mapstructure:",squash"`

	ctx interpolate.Context
}

type PostProcessor struct {
	config Config
	s3     *s3.Bucket
}

func (p *PostProcessor) Configure(raws ...interface{}) error {
	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{"output"},
		},
	}, raws...)
	if err != nil {
		return err
	}

	errs := new(packer.MultiError)
	// required configuration
	templates := map[string]*string{
		"region":   &p.config.Region,
		"bucket":   &p.config.Bucket,
		"manifest": &p.config.ManifestPath,
		"box_name": &p.config.BoxName,
		"box_dir":  &p.config.BoxDir,
		"version":  &p.config.Version,
	}

	for key, ptr := range templates {
		if *ptr == "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("vagrant-s3 %s must be set", key))
		}
	}

	// Template process
	for key, ptr := range templates {
		if err = interpolate.Validate(*ptr, &p.config.ctx); err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error parsing %s template: %s", key, err))
		}
	}

	auth, err := aws.GetAuth(p.config.AccessKey, p.config.SecretKey)
	if err != nil {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Unable to create Aws Authentication. Try providing keys 'access_key_id' and 'secret_key'"))
	}

	// determine region
	region, valid := aws.Regions[p.config.Region]
	if valid {
		p.s3 = s3.New(auth, region).Bucket(p.config.Bucket)
	} else {
		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Invalid region specified: %s", p.config.Region))
	}

	if p.config.ACL == "" {
		p.config.ACL = "public-read"
	}

	if len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	// Only accept input from the vagrant post-processor
	if artifact.BuilderId() != "mitchellh.post-processor.vagrant" {
		return nil, false, fmt.Errorf("Unknown artifact type, requires box from vagrant post-processor: %s", artifact.BuilderId())
	}

	// Assume there is only one .box file to upload
	box := artifact.Files()[0]
	if !strings.HasSuffix(box, ".box") {
		return nil, false, fmt.Errorf("Unknown files in artifact from vagrant post-processor: %s", artifact.Files())
	}

	provider := providerFromBuilderName(artifact.Id())
	ui.Say(fmt.Sprintf("Preparing to upload box for '%s' provider to S3 bucket '%s'", provider, p.config.Bucket))

	// open the box so we can upload to S3 and calculate checksum for the manifest
	file, err := os.Open(box)
	if err != nil {
		return nil, false, err
	}
	defer file.Close()

	// get the file's size
	info, err := file.Stat()
	if err != nil {
		return nil, false, err
	}
	size := info.Size()
	ui.Message(fmt.Sprintf("Box to upload: %s (%d bytes)", box, size))

	// get the latest manifest so we can add to it
	ui.Message("Fetching latest manifest")
	manifest, err := p.getManifest()
	if err != nil {
		return nil, false, err
	}

	// generate the path to store the box in S3
	boxPath := fmt.Sprintf("%s/%s/%s", p.config.BoxDir, p.config.Version, path.Base(box))

	ui.Message("Generating checksum")
	checksum, err := sum256(file)
	if err != nil {
		return nil, false, err
	}
	ui.Message(fmt.Sprintf("Checksum is %s", checksum))

	ui.Message(fmt.Sprintf("Adding %s %s box to manifest", provider, p.config.Version))
	if err := manifest.add(p.config.Version, &Provider{
		Name:         provider,
		Url:          p.s3.URL(boxPath),
		ChecksumType: "sha256",
		Checksum:     checksum,
	}); err != nil {
		return nil, false, err
	}

	// upload the box to S3 (rewinding as we already read the file to generate the checksum)
	ui.Message(fmt.Sprintf("Uploading box to S3: %s", boxPath))
	if _, err := file.Seek(0, 0); err != nil {
		return nil, false, err
	}
	if size > 100*1024*1024 {
		ui.Message("File size > 100MB. Initiating multipart upload")
		multi, err := p.s3.Multi(boxPath, "application/octet-stream", p.config.ACL)
		if err != nil {
			return nil, false, err
		}
		parts, err := multi.PutAll(file, 5*1024*1024)
		if err != nil {
			return nil, false, err
		}
		if err := multi.Complete(parts); err != nil {
			return nil, false, err
		}
	} else {
		if err := p.s3.PutReader(boxPath, file, size, "application/octet-stream", p.config.ACL); err != nil {
			return nil, false, err
		}
	}

	ui.Message(fmt.Sprintf("Uploading the manifest: %s", p.config.ManifestPath))
	if err := p.putManifest(manifest); err != nil {
		return nil, false, err
	}

	return &Artifact{p.s3.URL(p.config.ManifestPath)}, true, nil
}

func (p *PostProcessor) getManifest() (*Manifest, error) {
	body, err := p.s3.GetReader(p.config.ManifestPath)
	if err != nil {
		s3Err, ok := err.(*s3.Error)
		if ok && s3Err.Code == "NoSuchKey" {
			return &Manifest{Name: p.config.BoxName}, nil
		}
		return nil, err
	}
	defer body.Close()

	manifest := &Manifest{}
	if err := json.NewDecoder(body).Decode(manifest); err != nil {
		return nil, err
	}
	return manifest, nil
}

func (p *PostProcessor) putManifest(manifest *Manifest) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(manifest); err != nil {
		return err
	}
	if err := p.s3.Put(p.config.ManifestPath, buf.Bytes(), "application/json", p.config.ACL); err != nil {
		return err
	}
	return nil
}

// calculates a sha256 checksum of the file
func sum256(file *os.File) (string, error) {
	h := sha256.New()
	if _, err := io.Copy(h, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(h.Sum(nil)), nil
}

// converts a packer builder name to the corresponding vagrant provider
func providerFromBuilderName(name string) string {
	switch name {
	case "aws":
		return "aws"
	case "digitalocean":
		return "digitalocean"
	case "virtualbox":
		return "virtualbox"
	case "vmware":
		return "vmware_desktop"
	case "parallels":
		return "parallels"
	default:
		return name
	}
}
<|endoftext|>


<commit_before>package base

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"testing"

	goassert "github.com/couchbaselabs/go.assert"
	"github.com/stretchr/testify/assert"
)

var fileShouldLogTests = []struct {
	enabled     bool
	loggerLevel LogLevel
	logToLevel  LogLevel
	loggerKeys  []string
	logToKey    LogKey
	expected    bool
}{
	{
		// Log with matching log level
		enabled:     true,
		loggerLevel: LevelInfo,
		logToLevel:  LevelInfo,
		expected:    true,
	},
	{
		// Log with higher log level
		enabled:     true,
		loggerLevel: LevelInfo,
		logToLevel:  LevelWarn,
		expected:    true,
	},
	{
		// Log with lower log level
		enabled:     true,
		loggerLevel: LevelWarn,
		logToLevel:  LevelInfo,
		expected:    false,
	},
	{
		// Logger disabled (enabled = false)
		enabled:     false,
		loggerLevel: LevelNone,
		logToLevel:  LevelError,
		expected:    false,
	},
	{
		// Logger disabled (LevelNone)
		enabled:     true,
		loggerLevel: LevelNone,
		logToLevel:  LevelInfo,
		expected:    false,
	},
}

func TestFileShouldLog(t *testing.T) {
	for _, test := range fileShouldLogTests {
		name := fmt.Sprintf("logger{%s,%s}.shouldLog(%s,%s)",
			test.loggerLevel.StringShort(), test.loggerKeys,
			test.logToLevel.StringShort(), test.logToKey)

		l := FileLogger{
			Enabled: test.enabled,
			level:   test.loggerLevel,
			output:  ioutil.Discard,
			logger:  log.New(ioutil.Discard, "", 0),
		}

		t.Run(name, func(ts *testing.T) {
			got := l.shouldLog(test.logToLevel)
			goassert.Equals(ts, got, test.expected)
		})
	}
}

func BenchmarkFileShouldLog(b *testing.B) {
	for _, test := range fileShouldLogTests {
		name := fmt.Sprintf("logger{%s,%s}.shouldLog(%s,%s)",
			test.loggerLevel.StringShort(), test.loggerKeys,
			test.logToLevel.StringShort(), test.logToKey)

		l := FileLogger{
			Enabled: test.enabled,
			level:   test.loggerLevel,
			output:  ioutil.Discard,
			logger:  log.New(ioutil.Discard, "", 0),
		}

		b.Run(name, func(bb *testing.B) {
			for i := 0; i < bb.N; i++ {
				l.shouldLog(test.logToLevel)
			}
		})
	}
}

func TestRotatedLogDeletion(t *testing.T) {
	var dirContents []os.FileInfo

	//Regular Test With multiple files above high and low watermark
	dir, _ := ioutil.TempDir("", "tempdir1")

	err := makeTestFile(2, logFilePrefix+"error-2019-02-01T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"error-2019-02-01T12-10-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"error-2019-02-01T12-20-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-01T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-01T12-01-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-02T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-02T12-10-00.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 3, 5)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "info", 5, 7)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 3, len(dirContents))

	var fileNames = []string{}

	for fileIndex := range dirContents {
		fileNames = append(fileNames, dirContents[fileIndex].Name())
	}

	assert.Contains(t, fileNames, logFilePrefix+"error-2019-02-01T12-20-00.log.gz")
	assert.Contains(t, fileNames, logFilePrefix+"info-2019-02-02T12-00-00.log.gz")
	assert.Contains(t, fileNames, logFilePrefix+"info-2019-02-02T12-10-00.log.gz")

	os.RemoveAll(dir)

	//Hit low watermark but not high watermark
	dir, _ = ioutil.TempDir("", "tempdir2")
	err = makeTestFile(3, logFilePrefix+"error.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 4)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 1, len(dirContents))
	os.RemoveAll(dir)

	//Single file hitting low and high watermark
	dir, _ = ioutil.TempDir("", "tempdir3")
	err = makeTestFile(5, logFilePrefix+"error.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 4)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Empty(t, dirContents)
	os.RemoveAll(dir)

	//Not hitting low or high therefore no deletion
	dir, _ = ioutil.TempDir("", "tempdir4")
	err = makeTestFile(1, logFilePrefix+"error.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 4)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 1, len(dirContents))
	os.RemoveAll(dir)

	//Test deletion with files at the end of date boundaries
	dir, _ = ioutil.TempDir("", "tempdir5")
	err = makeTestFile(1, logFilePrefix+"error-2018-12-31T23-59-59.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"error-2019-01-01T00-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"error-2019-01-31T23-59-59.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"error-2019-01-01T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 3)
	assert.NoError(t, err)

	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 2, len(dirContents))

	fileNames = []string{}
	for fileIndex := range dirContents {
		fileNames = append(fileNames, dirContents[fileIndex].Name())
	}

	assert.Contains(t, fileNames, logFilePrefix+"error-2019-01-01T12-00-00.log.gz")
	assert.Contains(t, fileNames, logFilePrefix+"error-2019-01-31T23-59-59.log.gz")

	os.RemoveAll(dir)

	//Test deletion with no .gz files to ensure nothing is deleted
	dir, _ = ioutil.TempDir("", "tempdir6")
	err = makeTestFile(1, logFilePrefix+"error", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"info", dir)
	assert.NoError(t, err)

	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 2, len(dirContents))

	fileNames = []string{}
	for fileIndex := range dirContents {
		fileNames = append(fileNames, dirContents[fileIndex].Name())
	}

	assert.Contains(t, fileNames, logFilePrefix+"error")
	assert.Contains(t, fileNames, logFilePrefix+"info")

	os.RemoveAll(dir)
}

func makeTestFile(sizeMB int, name string, dir string) (err error) {
	f, err := os.Create(filepath.Join(dir, name))
	if err != nil {
		return err
	}

	if err := f.Truncate(int64(sizeMB * 1024 * 1024)); err != nil {
		return err
	}
	return nil
}
<commit_msg>Added f.Close() fix (#4060)<commit_after>package base

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"testing"

	goassert "github.com/couchbaselabs/go.assert"
	"github.com/stretchr/testify/assert"
)

var fileShouldLogTests = []struct {
	enabled     bool
	loggerLevel LogLevel
	logToLevel  LogLevel
	loggerKeys  []string
	logToKey    LogKey
	expected    bool
}{
	{
		// Log with matching log level
		enabled:     true,
		loggerLevel: LevelInfo,
		logToLevel:  LevelInfo,
		expected:    true,
	},
	{
		// Log with higher log level
		enabled:     true,
		loggerLevel: LevelInfo,
		logToLevel:  LevelWarn,
		expected:    true,
	},
	{
		// Log with lower log level
		enabled:     true,
		loggerLevel: LevelWarn,
		logToLevel:  LevelInfo,
		expected:    false,
	},
	{
		// Logger disabled (enabled = false)
		enabled:     false,
		loggerLevel: LevelNone,
		logToLevel:  LevelError,
		expected:    false,
	},
	{
		// Logger disabled (LevelNone)
		enabled:     true,
		loggerLevel: LevelNone,
		logToLevel:  LevelInfo,
		expected:    false,
	},
}

func TestFileShouldLog(t *testing.T) {
	for _, test := range fileShouldLogTests {
		name := fmt.Sprintf("logger{%s,%s}.shouldLog(%s,%s)",
			test.loggerLevel.StringShort(), test.loggerKeys,
			test.logToLevel.StringShort(), test.logToKey)

		l := FileLogger{
			Enabled: test.enabled,
			level:   test.loggerLevel,
			output:  ioutil.Discard,
			logger:  log.New(ioutil.Discard, "", 0),
		}

		t.Run(name, func(ts *testing.T) {
			got := l.shouldLog(test.logToLevel)
			goassert.Equals(ts, got, test.expected)
		})
	}
}

func BenchmarkFileShouldLog(b *testing.B) {
	for _, test := range fileShouldLogTests {
		name := fmt.Sprintf("logger{%s,%s}.shouldLog(%s,%s)",
			test.loggerLevel.StringShort(), test.loggerKeys,
			test.logToLevel.StringShort(), test.logToKey)

		l := FileLogger{
			Enabled: test.enabled,
			level:   test.loggerLevel,
			output:  ioutil.Discard,
			logger:  log.New(ioutil.Discard, "", 0),
		}

		b.Run(name, func(bb *testing.B) {
			for i := 0; i < bb.N; i++ {
				l.shouldLog(test.logToLevel)
			}
		})
	}
}

func TestRotatedLogDeletion(t *testing.T) {
	var dirContents []os.FileInfo

	//Regular Test With multiple files above high and low watermark
	dir, _ := ioutil.TempDir("", "tempdir1")

	err := makeTestFile(2, logFilePrefix+"error-2019-02-01T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"error-2019-02-01T12-10-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"error-2019-02-01T12-20-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-01T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-01T12-01-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-02T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(2, logFilePrefix+"info-2019-02-02T12-10-00.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 3, 5)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "info", 5, 7)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 3, len(dirContents))

	var fileNames = []string{}

	for fileIndex := range dirContents {
		fileNames = append(fileNames, dirContents[fileIndex].Name())
	}

	assert.Contains(t, fileNames, logFilePrefix+"error-2019-02-01T12-20-00.log.gz")
	assert.Contains(t, fileNames, logFilePrefix+"info-2019-02-02T12-00-00.log.gz")
	assert.Contains(t, fileNames, logFilePrefix+"info-2019-02-02T12-10-00.log.gz")

	os.RemoveAll(dir)

	//Hit low watermark but not high watermark
	dir, _ = ioutil.TempDir("", "tempdir2")
	err = makeTestFile(3, logFilePrefix+"error.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 4)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 1, len(dirContents))
	os.RemoveAll(dir)

	//Single file hitting low and high watermark
	dir, _ = ioutil.TempDir("", "tempdir3")
	err = makeTestFile(5, logFilePrefix+"error.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 4)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Empty(t, dirContents)
	os.RemoveAll(dir)

	//Not hitting low or high therefore no deletion
	dir, _ = ioutil.TempDir("", "tempdir4")
	err = makeTestFile(1, logFilePrefix+"error.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 4)
	assert.NoError(t, err)
	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 1, len(dirContents))
	os.RemoveAll(dir)

	//Test deletion with files at the end of date boundaries
	dir, _ = ioutil.TempDir("", "tempdir5")
	err = makeTestFile(1, logFilePrefix+"error-2018-12-31T23-59-59.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"error-2019-01-01T00-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"error-2019-01-31T23-59-59.log.gz", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"error-2019-01-01T12-00-00.log.gz", dir)
	assert.NoError(t, err)
	err = runLogDeletion(dir, "error", 2, 3)
	assert.NoError(t, err)

	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 2, len(dirContents))

	fileNames = []string{}
	for fileIndex := range dirContents {
		fileNames = append(fileNames, dirContents[fileIndex].Name())
	}

	assert.Contains(t, fileNames, logFilePrefix+"error-2019-01-01T12-00-00.log.gz")
	assert.Contains(t, fileNames, logFilePrefix+"error-2019-01-31T23-59-59.log.gz")

	os.RemoveAll(dir)

	//Test deletion with no .gz files to ensure nothing is deleted
	dir, _ = ioutil.TempDir("", "tempdir6")
	err = makeTestFile(1, logFilePrefix+"error", dir)
	assert.NoError(t, err)
	err = makeTestFile(1, logFilePrefix+"info", dir)
	assert.NoError(t, err)

	dirContents, err = ioutil.ReadDir(dir)
	assert.Equal(t, 2, len(dirContents))

	fileNames = []string{}
	for fileIndex := range dirContents {
		fileNames = append(fileNames, dirContents[fileIndex].Name())
	}

	assert.Contains(t, fileNames, logFilePrefix+"error")
	assert.Contains(t, fileNames, logFilePrefix+"info")

	os.RemoveAll(dir)
}

func makeTestFile(sizeMB int, name string, dir string) (err error) {
	f, err := os.Create(filepath.Join(dir, name))
	if err != nil {
		return err
	}

	defer f.Close()

	if err := f.Truncate(int64(sizeMB * 1024 * 1024)); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package suggest

import (
	"testing"
	"os"
	"log"
	"bufio"
)

func TestOnDiscWriter_Save(t *testing.T) {
	header, err := os.Create("testdata/db/test.hd")
	defer header.Close()
	if err != nil {
		log.Fatal(err)
	}

	docList, err := os.Create("testdata/db/test.dl")
	defer header.Close()
	if err != nil {
		log.Fatal(err)
	}

	dict, err := os.Open("testdata/cars.dict")
	defer dict.Close()
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(dict)
	collection := make([]string, 0)
	for scanner.Scan() {
		collection = append(collection, scanner.Text())
	}

	index := buildIndex()
	writer := &onDiscWriter{VBEncoder(), header, docList, 0}
	writer.Save(index)

	reader := &onDiscReader{VBDecoder(), header, docList, 0}
	reader.Load()
}

func buildIndex() Index {
	dict, err := os.Open("testdata/cars.dict")
	defer dict.Close()
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(dict)
	collection := make([]string, 0)
	for scanner.Scan() {
		collection = append(collection, scanner.Text())
	}

	dictionary := NewInMemoryDictionary(collection)

	alphabet := NewCompositeAlphabet([]Alphabet{
		NewRussianAlphabet(),
		NewEnglishAlphabet(),
		NewNumberAlphabet(),
		NewSimpleAlphabet([]rune{'$'}),
	})

	indexer := NewIndexer(3, NewGenerator(3, alphabet), NewCleaner(alphabet.Chars(), "$", "$"))

	return indexer.Index(dictionary)
}
<commit_msg>storage_test remove test generated files on test teardown<commit_after>package suggest

import (
	"testing"
	"os"
	"log"
	"bufio"
)

func TestOnDiscWriter_Save(t *testing.T) {
	header, err := os.Create("testdata/db/test.hd")
	defer func() {
		header.Close()
		os.Remove(header.Name())
	}()
	if err != nil {
		log.Fatal(err)
	}

	docList, err := os.Create("testdata/db/test.dl")
	defer func () {
		docList.Close()
		os.Remove(docList.Name())
	}()

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

	dict, err := os.Open("testdata/cars.dict")
	defer dict.Close()
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(dict)
	collection := make([]string, 0)
	for scanner.Scan() {
		collection = append(collection, scanner.Text())
	}

	index := buildIndex()
	writer := &onDiscWriter{VBEncoder(), header, docList, 0}
	writer.Save(index)

	reader := &onDiscReader{VBDecoder(), header, docList, 0}
	reader.Load()
}

func buildIndex() Index {
	dict, err := os.Open("testdata/cars.dict")
	defer dict.Close()
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(dict)
	collection := make([]string, 0)
	for scanner.Scan() {
		collection = append(collection, scanner.Text())
	}

	dictionary := NewInMemoryDictionary(collection)

	alphabet := NewCompositeAlphabet([]Alphabet{
		NewRussianAlphabet(),
		NewEnglishAlphabet(),
		NewNumberAlphabet(),
		NewSimpleAlphabet([]rune{'$'}),
	})

	indexer := NewIndexer(3, NewGenerator(3, alphabet), NewCleaner(alphabet.Chars(), "$", "$"))

	return indexer.Index(dictionary)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/gnuflag"
	"github.com/lxc/lxd/shared/i18n"
)

type actionCmd struct {
	action         shared.ContainerAction
	hasTimeout     bool
	visible        bool
	name           string
	timeout        int
	force          bool
	stateful       bool
	stateless      bool
	additionalHelp string
}

func (c *actionCmd) showByDefault() bool {
	return c.visible
}

func (c *actionCmd) usage() string {
	if c.additionalHelp != "" {
		c.additionalHelp = fmt.Sprintf("\n\n%s", c.additionalHelp)
	}

	return fmt.Sprintf(i18n.G(
		`Changes state of one or more containers to %s.

lxc %s <name> [<name>...]%s`), c.name, c.name, c.additionalHelp)
}

func (c *actionCmd) flags() {
	if c.hasTimeout {
		gnuflag.IntVar(&c.timeout, "timeout", -1, i18n.G("Time to wait for the container before killing it."))
		gnuflag.BoolVar(&c.force, "f", false, i18n.G("Force the container to shutdown."))
		gnuflag.BoolVar(&c.force, "force", false, i18n.G("Force the container to shutdown."))
	}
	gnuflag.BoolVar(&c.stateful, "stateful", false, i18n.G("Store the container state (only for stop)."))
	gnuflag.BoolVar(&c.stateless, "stateless", false, i18n.G("Ignore the container state (only for start)."))
}

func (c *actionCmd) run(config *lxd.Config, args []string) error {
	if len(args) == 0 {
		return errArgs
	}

	state := false

	// Only store state if asked to
	if c.action == "stop" && c.stateful {
		state = true
	}

	for _, nameArg := range args {
		remote, name := config.ParseRemoteAndContainer(nameArg)
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		if name == "" {
			return fmt.Errorf(i18n.G("Must supply container name for: ")+"\"%s\"", nameArg)
		}

		if c.action == shared.Start {
			current, err := d.ContainerInfo(name)
			if err != nil {
				return err
			}

			// "start" for a frozen container means "unfreeze"
			if current.StatusCode == shared.Frozen {
				c.action = shared.Unfreeze
			}

			// Always restore state (if present) unless asked not to
			if c.action == shared.Start && current.Stateful && !c.stateless {
				state = true
			}
		}

		resp, err := d.Action(name, c.action, c.timeout, c.force, state)
		if err != nil {
			return err
		}

		if resp.Type != lxd.Async {
			return fmt.Errorf(i18n.G("bad result type from action"))
		}

		if err := d.WaitForSuccess(resp.Operation); err != nil {
			return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, nameArg)
		}
	}
	return nil
}
<commit_msg>action: Update help<commit_after>package main

import (
	"fmt"

	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/gnuflag"
	"github.com/lxc/lxd/shared/i18n"
)

type actionCmd struct {
	action         shared.ContainerAction
	hasTimeout     bool
	visible        bool
	name           string
	timeout        int
	force          bool
	stateful       bool
	stateless      bool
	additionalHelp string
}

func (c *actionCmd) showByDefault() bool {
	return c.visible
}

func (c *actionCmd) usage() string {
	if c.additionalHelp != "" {
		c.additionalHelp = fmt.Sprintf("\n\n%s", c.additionalHelp)
	}

	return fmt.Sprintf(i18n.G(
		`Change state of one or more containers to %s.

lxc %s [<remote>:]<container> [[<remote>:]<container>...]%s`), c.name, c.name, c.additionalHelp)
}

func (c *actionCmd) flags() {
	if c.hasTimeout {
		gnuflag.IntVar(&c.timeout, "timeout", -1, i18n.G("Time to wait for the container before killing it"))
		gnuflag.BoolVar(&c.force, "f", false, i18n.G("Force the container to shutdown"))
		gnuflag.BoolVar(&c.force, "force", false, i18n.G("Force the container to shutdown"))
	}
	gnuflag.BoolVar(&c.stateful, "stateful", false, i18n.G("Store the container state (only for stop)"))
	gnuflag.BoolVar(&c.stateless, "stateless", false, i18n.G("Ignore the container state (only for start)"))
}

func (c *actionCmd) run(config *lxd.Config, args []string) error {
	if len(args) == 0 {
		return errArgs
	}

	state := false

	// Only store state if asked to
	if c.action == "stop" && c.stateful {
		state = true
	}

	for _, nameArg := range args {
		remote, name := config.ParseRemoteAndContainer(nameArg)
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		if name == "" {
			return fmt.Errorf(i18n.G("Must supply container name for: ")+"\"%s\"", nameArg)
		}

		if c.action == shared.Start {
			current, err := d.ContainerInfo(name)
			if err != nil {
				return err
			}

			// "start" for a frozen container means "unfreeze"
			if current.StatusCode == shared.Frozen {
				c.action = shared.Unfreeze
			}

			// Always restore state (if present) unless asked not to
			if c.action == shared.Start && current.Stateful && !c.stateless {
				state = true
			}
		}

		resp, err := d.Action(name, c.action, c.timeout, c.force, state)
		if err != nil {
			return err
		}

		if resp.Type != lxd.Async {
			return fmt.Errorf(i18n.G("bad result type from action"))
		}

		if err := d.WaitForSuccess(resp.Operation); err != nil {
			return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, nameArg)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/coreos/go-etcd/etcd"
	"os"
	"os/exec"
	"strings"
)

var key = flag.String("key", "", "etcd key")

func main() {
	flag.Parse()
	if *key == "" {
		fmt.Fprintln(os.Stderr, "etcdenv [-key=key] [...]")
		flag.PrintDefaults()
		os.Exit(1)
	}
	client := etcd.NewClient()
	res, err := client.Get(*key)

	if flag.NArg() > 0 {
		if err == nil {
			for _, n := range res {
				if strings.Contains(n.Value, "\n") {
					continue
				}
				key := strings.Split(n.Key, "/")
				k, v := strings.ToUpper(key[len(key)-1]), n.Value
				fmt.Println("creating env var:", k)
				os.Setenv(k, v)
			}
		}
		cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
		cmd.Stderr = os.Stderr
		cmd.Stdout = os.Stdout
		cmd.Stdin = os.Stdin
		err = cmd.Run()
		if err != nil {
			os.Exit(1)
		}
	} else {
		if err == nil {
			for _, n := range res {
				if strings.Contains(n.Value, "\n") {
					continue
				}
				key := strings.Split(n.Key, "/")
				k, v := strings.ToUpper(key[len(key)-1]), n.Value
				fmt.Printf("%s=%s\n", k, v)
			}
		} else {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}
<commit_msg>Newlines should be valid within environment variable values. Closes #1<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/coreos/go-etcd/etcd"
	"os"
	"os/exec"
	"strings"
)

var key = flag.String("key", "", "etcd key")

func main() {
	flag.Parse()
	if *key == "" {
		fmt.Fprintln(os.Stderr, "etcdenv [-key=key] [...]")
		flag.PrintDefaults()
		os.Exit(1)
	}
	client := etcd.NewClient()
	res, err := client.Get(*key)

	if flag.NArg() > 0 {
		if err == nil {
			for _, n := range res {
				key := strings.Split(n.Key, "/")
				k, v := strings.ToUpper(key[len(key)-1]), n.Value
				fmt.Println("creating env var:", k)
				os.Setenv(k, v)
			}
		}
		cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
		cmd.Stderr = os.Stderr
		cmd.Stdout = os.Stdout
		cmd.Stdin = os.Stdin
		err = cmd.Run()
		if err != nil {
			os.Exit(1)
		}
	} else {
		if err == nil {
			for _, n := range res {
				key := strings.Split(n.Key, "/")
				k, v := strings.ToUpper(key[len(key)-1]), n.Value
				fmt.Printf("%s=%s\n", k, v)
			}
		} else {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}
<|endoftext|>


<commit_before>package eval

import (
	"fmt"
	"reflect"

	"github.com/elves/elvish/eval/vars"
)

// Ns is a map from names to variables.
type Ns map[string]vars.Type

var _ interface{} = Ns(nil)

// NewNs creates an empty namespace.
func NewNs() Ns {
	return make(Ns)
}

func (Ns) Kind() string {
	return "ns"
}

func (ns Ns) Hash() uint32 {
	return uint32(addrOf(ns))
}

func (ns Ns) Equal(rhs interface{}) bool {
	if ns2, ok := rhs.(Ns); ok {
		return addrOf(ns) == addrOf(ns2)
	}
	return false
}

func (ns Ns) Repr(int) string {
	return fmt.Sprintf("<ns 0x%x>", addrOf(ns))
}

func (ns Ns) Get(k interface{}) (interface{}, bool) {
	if kstring, ok := k.(string); ok {
		if v, ok := ns[kstring]; ok {
			return v.Get(), true
		}
	}
	return nil, false
}

// HasName reports the namespace contains the given name.
func (ns Ns) HasName(name string) bool {
	_, ok := ns[name]
	return ok
}

// PopName removes a name from the namespace and returns the variable it used to
// contain.
func (ns Ns) PopName(name string) vars.Type {
	v := ns[name]
	delete(ns, name)
	return v
}

// Clone returns a shallow copy of the namespace.
func (ns Ns) Clone() Ns {
	ns2 := make(Ns)
	for name, variable := range ns {
		ns2[name] = variable
	}
	return ns2
}

// Add adds a variable to the namespace and returns the namespace itself.
func (ns Ns) Add(name string, v vars.Type) Ns {
	ns[name] = v
	return ns
}

// AddFn adds a function to a namespace. It returns the namespace itself.
func (ns Ns) AddFn(name string, v Callable) Ns {
	return ns.Add(name+FnSuffix, vars.NewFromPtr(&v))
}

// AddNs adds a sub-namespace to a namespace. It returns the namespace itself.
func (ns Ns) AddNs(name string, v Ns) Ns {
	return ns.Add(name+NsSuffix, vars.NewFromPtr(&v))
}

// AddBuiltinFn adds a builtin function to a namespace. It returns the namespace
// itself.
func (ns Ns) AddBuiltinFn(nsName, name string, impl interface{}) Ns {
	return ns.AddFn(name, NewBuiltinFn(nsName+name, impl))
}

// AddBuiltinFns adds builtin functions to a namespace. It returns the namespace
// itself.
func (ns Ns) AddBuiltinFns(nsName string, fns map[string]interface{}) Ns {
	for name, impl := range fns {
		ns.AddBuiltinFn(nsName, name, impl)
	}
	return ns
}

func addrOf(a interface{}) uintptr {
	return reflect.ValueOf(a).Pointer()
}

func (ns Ns) static() staticNs {
	static := make(staticNs)
	for name := range ns {
		static.set(name)
	}
	return static
}

// staticNs represents static information of an Ns.
type staticNs map[string]struct{}

func (ns staticNs) set(name string) {
	ns[name] = struct{}{}
}

func (ns staticNs) del(name string) {
	delete(ns, name)
}

func (ns staticNs) has(name string) bool {
	_, ok := ns[name]
	return ok
}
<commit_msg>Support iterating keys of namespaces.<commit_after>package eval

import (
	"fmt"
	"reflect"

	"github.com/elves/elvish/eval/vars"
)

// Ns is a map from names to variables.
type Ns map[string]vars.Type

var _ interface{} = Ns(nil)

// NewNs creates an empty namespace.
func NewNs() Ns {
	return make(Ns)
}

func (Ns) Kind() string {
	return "ns"
}

func (ns Ns) Hash() uint32 {
	return uint32(addrOf(ns))
}

func (ns Ns) Equal(rhs interface{}) bool {
	if ns2, ok := rhs.(Ns); ok {
		return addrOf(ns) == addrOf(ns2)
	}
	return false
}

func (ns Ns) Repr(int) string {
	return fmt.Sprintf("<ns 0x%x>", addrOf(ns))
}

func (ns Ns) Get(k interface{}) (interface{}, bool) {
	if kstring, ok := k.(string); ok {
		if v, ok := ns[kstring]; ok {
			return v.Get(), true
		}
	}
	return nil, false
}

func (ns Ns) IterateKeys(f func(interface{}) bool) {
	for k := range ns {
		if !f(k) {
			break
		}
	}
}

// HasName reports the namespace contains the given name.
func (ns Ns) HasName(name string) bool {
	_, ok := ns[name]
	return ok
}

// PopName removes a name from the namespace and returns the variable it used to
// contain.
func (ns Ns) PopName(name string) vars.Type {
	v := ns[name]
	delete(ns, name)
	return v
}

// Clone returns a shallow copy of the namespace.
func (ns Ns) Clone() Ns {
	ns2 := make(Ns)
	for name, variable := range ns {
		ns2[name] = variable
	}
	return ns2
}

// Add adds a variable to the namespace and returns the namespace itself.
func (ns Ns) Add(name string, v vars.Type) Ns {
	ns[name] = v
	return ns
}

// AddFn adds a function to a namespace. It returns the namespace itself.
func (ns Ns) AddFn(name string, v Callable) Ns {
	return ns.Add(name+FnSuffix, vars.NewFromPtr(&v))
}

// AddNs adds a sub-namespace to a namespace. It returns the namespace itself.
func (ns Ns) AddNs(name string, v Ns) Ns {
	return ns.Add(name+NsSuffix, vars.NewFromPtr(&v))
}

// AddBuiltinFn adds a builtin function to a namespace. It returns the namespace
// itself.
func (ns Ns) AddBuiltinFn(nsName, name string, impl interface{}) Ns {
	return ns.AddFn(name, NewBuiltinFn(nsName+name, impl))
}

// AddBuiltinFns adds builtin functions to a namespace. It returns the namespace
// itself.
func (ns Ns) AddBuiltinFns(nsName string, fns map[string]interface{}) Ns {
	for name, impl := range fns {
		ns.AddBuiltinFn(nsName, name, impl)
	}
	return ns
}

func addrOf(a interface{}) uintptr {
	return reflect.ValueOf(a).Pointer()
}

func (ns Ns) static() staticNs {
	static := make(staticNs)
	for name := range ns {
		static.set(name)
	}
	return static
}

// staticNs represents static information of an Ns.
type staticNs map[string]struct{}

func (ns staticNs) set(name string) {
	ns[name] = struct{}{}
}

func (ns staticNs) del(name string) {
	delete(ns, name)
}

func (ns staticNs) has(name string) bool {
	_, ok := ns[name]
	return ok
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "fmt"
    "encoding/json"
    "github.com/toke/golang-callmon"
)

func handleMessages(msgchan <-chan fritzbox.FbEvent){
  for {
      ev := <- msgchan

      jsonm,_ := json.Marshal(&ev)
      fmt.Printf("Some JSON: %s\n", jsonm)

      if ev.EventName == fritzbox.CALL {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else if ev.EventName == fritzbox.RING {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else {
          fmt.Printf("! %s\n", ev)
      }
  }
}

func mainloop(host string) {
  c := new(fritzbox.CallmonHandler).Connect(host)

  defer c.Close()

  if c.Connected {
    recv := make(chan fritzbox.FbEvent)
    go handleMessages(recv)

    // Inject a test message
    f := c.Parse("06.08.14 14:52:26;CALL;1;10;50000001;012344567;SIP1;")
    recv <- f

    c.Loop(recv)
  }
}

func main() {
  arg := os.Args

  host := "fritz.box"
  if (len(arg) > 1 && arg[1] != "") {
    host = arg[1]
  }

  mainloop(host)
  fmt.Println("NEVER EVER GONNA GIVE YOU UP")
}
<commit_msg>corrected import<commit_after>package main

import (
    "os"
    "fmt"
    "encoding/json"
    "github.com/toke/golang-callmon/fritzbox"
)

func handleMessages(msgchan <-chan fritzbox.FbEvent){
  for {
      ev := <- msgchan

      jsonm,_ := json.Marshal(&ev)
      fmt.Printf("Some JSON: %s\n", jsonm)

      if ev.EventName == fritzbox.CALL {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else if ev.EventName == fritzbox.RING {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else {
          fmt.Printf("! %s\n", ev)
      }
  }
}

func mainloop(host string) {
  c := new(fritzbox.CallmonHandler).Connect(host)

  defer c.Close()

  if c.Connected {
    recv := make(chan fritzbox.FbEvent)
    go handleMessages(recv)

    // Inject a test message
    f := c.Parse("06.08.14 14:52:26;CALL;1;10;50000001;012344567;SIP1;")
    recv <- f

    c.Loop(recv)
  }
}

func main() {
  arg := os.Args

  host := "fritz.box"
  if (len(arg) > 1 && arg[1] != "") {
    host = arg[1]
  }

  mainloop(host)
  fmt.Println("NEVER EVER GONNA GIVE YOU UP")
}
<|endoftext|>


<commit_before>package process

import (
	"context"
	"github.com/whosonfirst/go-whosonfirst-geojson-v2/feature"
	idx "github.com/whosonfirst/go-whosonfirst-index"
	"github.com/whosonfirst/go-whosonfirst-log"
	"github.com/whosonfirst/go-whosonfirst-tile38"
	"github.com/whosonfirst/go-whosonfirst-tile38/index"
	"github.com/whosonfirst/go-whosonfirst-updated"
	"github.com/whosonfirst/go-whosonfirst-updated/queue"
	"github.com/whosonfirst/go-whosonfirst-updated/utils"
	"github.com/whosonfirst/go-whosonfirst-uri"
	"io"
	"os"
	"path/filepath"
	"sync"
)

type Tile38Process struct {
	Process
	queue      *queue.Queue
	indexer    *index.Tile38Indexer
	data_root  string
	flushing   bool
	mu         *sync.Mutex
	files      map[string][]string
	collection string
	logger     *log.WOFLogger
}

func NewTile38Process(data_root string, t38_clients []tile38.Tile38Client, t38_collection string, logger *log.WOFLogger) (*Tile38Process, error) {

	data_root, err := filepath.Abs(data_root)

	if err != nil {
		return nil, err
	}

	_, err = os.Stat(data_root)

	if os.IsNotExist(err) {
		return nil, err
	}

	t38_indexer, err := index.NewTile38Indexer(t38_clients...)

	q, err := queue.NewQueue()

	if err != nil {
		return nil, err
	}

	files := make(map[string][]string)

	mu := new(sync.Mutex)

	pr := Tile38Process{
		indexer:    t38_indexer,
		data_root:  data_root,
		collection: t38_collection,
		queue:      q,
		flushing:   false,
		mu:         mu,
		files:      files,
		logger:     logger,
	}

	return &pr, nil
}

func (pr *Tile38Process) Name() string {
	return "tile38"
}

func (pr *Tile38Process) Flush() error {

	pr.mu.Lock()

	if pr.flushing {
		pr.mu.Unlock()
		return nil
	}

	pr.flushing = true
	pr.mu.Unlock()

	for _, repo := range pr.queue.Pending() {
		go pr.ProcessRepo(repo)
	}

	pr.mu.Lock()

	pr.flushing = false
	pr.mu.Unlock()

	return nil
}

func (pr *Tile38Process) ProcessTask(task updated.UpdateTask) error {

	repo := task.Repo

	pr.mu.Lock()

	files, ok := pr.files[repo]

	if !ok {
		files = make([]string, 0)
	}

	for _, path := range task.Commits {

		is_wof, _ := uri.IsWOFFile(path)

		if !is_wof {
			continue
		}

		is_alt, _ := uri.IsAltFile(path)

		if is_alt {
			continue
		}

		files = append(files, path)
	}

	pr.files[repo] = files
	pr.mu.Unlock()

	return pr.ProcessRepo(repo)
}

func (pr *Tile38Process) ProcessRepo(repo string) error {

	if pr.queue.IsProcessing(repo) {

		return pr.queue.Schedule(repo)
	}

	err := pr.queue.Lock(repo)

	if err != nil {
		return err
	}

	if len(pr.files[repo]) > 0 {

		err = pr._process(repo)

		if err != nil {
			return err
		}
	}

	err = pr.queue.Release(repo)

	if err != nil {
		return err
	}

	return nil
}

func (pr *Tile38Process) _process(repo string) error {

	root := filepath.Join(pr.data_root, repo)

	_, err := os.Stat(root)

	if os.IsNotExist(err) {
		pr.logger.Error("Can't find repo", root)
		return err
	}

	/* sudo wrap all of this in a single function somewhere... */

	pr.mu.Lock()
	files := pr.files[repo]

	delete(pr.files, repo)
	pr.mu.Unlock()

	tmpfile, err := utils.FilesToFileList(files, root)

	if err != nil {

		pr.mu.Lock()

		_, ok := pr.files[repo]

		if ok {

			for _, path := range files {
				pr.files[repo] = append(pr.files[repo], path)
			}

		} else {
			pr.files[repo] = files
		}

		pr.mu.Unlock()

		return err
	}

	defer func() {
		tmpfile.Close()
		os.Remove(tmpfile.Name())
	}()

	/*
		err = pr.indexer.IndexFileList(tmpfile.Name(), pr.collection)

		if err != nil {
			pr.logger.Error("Failed to process (Tile38) file list because %s (%s)", err, tmpfile.Name())
			return err
		}
	*/

	cb := func(fh io.Reader, ctx context.Context, args ...interface{}) error {

		f, err := feature.LoadWOFFeatureFromReader(fh)

		if err != nil {
			return err
		}

		return pr.indexer.IndexFeature(f, pr.collection)
	}

	wof_indexer, err := idx.NewIndexer("filelist", cb)

	if err != nil {
		pr.logger.Fatal("Failed to create new indexer because %s", err)
	}

	paths := []string{tmpfile.Name()}

	err = wof_indexer.IndexPaths(paths)

	if err != nil {
		pr.logger.Fatal("Failed to index %s mode because %s", tmpfile.Name(), err)
	}

	pr.logger.Debug("Successfully processed (Tile38) file list %s", tmpfile.Name())

	return nil

}
<commit_msg>add timings for T38<commit_after>package process

import (
	"context"
	"github.com/whosonfirst/go-whosonfirst-geojson-v2/feature"
	idx "github.com/whosonfirst/go-whosonfirst-index"
	"github.com/whosonfirst/go-whosonfirst-log"
	"github.com/whosonfirst/go-whosonfirst-tile38"
	"github.com/whosonfirst/go-whosonfirst-tile38/index"
	"github.com/whosonfirst/go-whosonfirst-updated"
	"github.com/whosonfirst/go-whosonfirst-updated/queue"
	"github.com/whosonfirst/go-whosonfirst-updated/utils"
	"github.com/whosonfirst/go-whosonfirst-uri"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"
)

type Tile38Process struct {
	Process
	queue      *queue.Queue
	indexer    *index.Tile38Indexer
	data_root  string
	flushing   bool
	mu         *sync.Mutex
	files      map[string][]string
	collection string
	logger     *log.WOFLogger
}

func NewTile38Process(data_root string, t38_clients []tile38.Tile38Client, t38_collection string, logger *log.WOFLogger) (*Tile38Process, error) {

	data_root, err := filepath.Abs(data_root)

	if err != nil {
		return nil, err
	}

	_, err = os.Stat(data_root)

	if os.IsNotExist(err) {
		return nil, err
	}

	t38_indexer, err := index.NewTile38Indexer(t38_clients...)

	q, err := queue.NewQueue()

	if err != nil {
		return nil, err
	}

	files := make(map[string][]string)

	mu := new(sync.Mutex)

	pr := Tile38Process{
		indexer:    t38_indexer,
		data_root:  data_root,
		collection: t38_collection,
		queue:      q,
		flushing:   false,
		mu:         mu,
		files:      files,
		logger:     logger,
	}

	return &pr, nil
}

func (pr *Tile38Process) Name() string {
	return "tile38"
}

func (pr *Tile38Process) Flush() error {

	pr.mu.Lock()

	if pr.flushing {
		pr.mu.Unlock()
		return nil
	}

	pr.flushing = true
	pr.mu.Unlock()

	for _, repo := range pr.queue.Pending() {
		go pr.ProcessRepo(repo)
	}

	pr.mu.Lock()

	pr.flushing = false
	pr.mu.Unlock()

	return nil
}

func (pr *Tile38Process) ProcessTask(task updated.UpdateTask) error {

	repo := task.Repo

	pr.mu.Lock()

	files, ok := pr.files[repo]

	if !ok {
		files = make([]string, 0)
	}

	for _, path := range task.Commits {

		is_wof, _ := uri.IsWOFFile(path)

		if !is_wof {
			continue
		}

		is_alt, _ := uri.IsAltFile(path)

		if is_alt {
			continue
		}

		files = append(files, path)
	}

	pr.files[repo] = files
	pr.mu.Unlock()

	return pr.ProcessRepo(repo)
}

func (pr *Tile38Process) ProcessRepo(repo string) error {

	if pr.queue.IsProcessing(repo) {

		return pr.queue.Schedule(repo)
	}

	err := pr.queue.Lock(repo)

	if err != nil {
		return err
	}

	if len(pr.files[repo]) > 0 {

		err = pr._process(repo)

		if err != nil {
			return err
		}
	}

	err = pr.queue.Release(repo)

	if err != nil {
		return err
	}

	return nil
}

func (pr *Tile38Process) _process(repo string) error {

	t1 := time.Now()

	defer func() {
		t2 := time.Since(t1)
		pr.logger.Status("Time to process (%s) %s: %v", pr.Name(), repo, t2)
	}()

	root := filepath.Join(pr.data_root, repo)

	_, err := os.Stat(root)

	if os.IsNotExist(err) {
		pr.logger.Error("Can't find repo", root)
		return err
	}

	/* sudo wrap all of this in a single function somewhere... */

	pr.mu.Lock()
	files := pr.files[repo]

	delete(pr.files, repo)
	pr.mu.Unlock()

	tmpfile, err := utils.FilesToFileList(files, root)

	if err != nil {

		pr.mu.Lock()

		_, ok := pr.files[repo]

		if ok {

			for _, path := range files {
				pr.files[repo] = append(pr.files[repo], path)
			}

		} else {
			pr.files[repo] = files
		}

		pr.mu.Unlock()

		return err
	}

	defer func() {
		tmpfile.Close()
		os.Remove(tmpfile.Name())
	}()

	/*
		err = pr.indexer.IndexFileList(tmpfile.Name(), pr.collection)

		if err != nil {
			pr.logger.Error("Failed to process (Tile38) file list because %s (%s)", err, tmpfile.Name())
			return err
		}
	*/

	cb := func(fh io.Reader, ctx context.Context, args ...interface{}) error {

		f, err := feature.LoadWOFFeatureFromReader(fh)

		if err != nil {
			return err
		}

		return pr.indexer.IndexFeature(f, pr.collection)
	}

	wof_indexer, err := idx.NewIndexer("filelist", cb)

	if err != nil {
		pr.logger.Fatal("Failed to create new indexer because %s", err)
	}

	paths := []string{tmpfile.Name()}

	err = wof_indexer.IndexPaths(paths)

	if err != nil {
		pr.logger.Fatal("Failed to index %s mode because %s", tmpfile.Name(), err)
	}

	pr.logger.Debug("Successfully processed (Tile38) file list %s", tmpfile.Name())

	return nil

}
<|endoftext|>


<commit_before>package robot

// See defs.go for other definitions

// Step 1
// Define Dir type here.
// Define N, E, S, W here.

func Right() {
	panic("Please implement the Right function")
}

func Left() {
	panic("Please implement the Left function")
}

func Advance() {
	panic("Please implement the Advance function")
}

func (d Dir) String() string {
	panic("Please implement the String function")
}

// Step 2
// Define Action type here.

func StartRobot(command chan Command, action chan Action) {
	panic("Please implement the StartRobot function")
}

func Room(extent Rect, robot Step2Robot, action chan Action, report chan Step2Robot) {
	panic("Please implement the Room function")
}

// Step 3
// Define Action3 type here.

func StartRobot3(name, script string, action chan Action3, log chan string) {
	panic("Please implement the StartRobot3 function")
}

func Room3(extent Rect, robots []Step3Robot, action chan Action3, rep chan []Step3Robot, log chan string) {
	panic("Please implement the Room3 function")
}
<commit_msg>Pass part 1<commit_after>package robot

import (
	"fmt"
	"log"
)

// See defs.go for other definitions

// Step 1
// Define Dir type here.

// Define N, E, S, W here.
const N Dir = 0
const E Dir = 1
const S Dir = 2
const W Dir = 3

func Right() {
	switch Step1Robot.Dir {
	case N:
		Step1Robot.Dir = E
	case E:
		Step1Robot.Dir = S
	case S:
		Step1Robot.Dir = W
	case W:
		Step1Robot.Dir = N
	default:
		log.Fatalf("unrecognized direction %d", Step1Robot.Dir)
	}
}

func Left() {
	switch Step1Robot.Dir {
	case N:
		Step1Robot.Dir = W
	case E:
		Step1Robot.Dir = N
	case S:
		Step1Robot.Dir = E
	case W:
		Step1Robot.Dir = S
	default:
		log.Fatalf("unrecognized direction %d", Step1Robot.Dir)
	}
}

func Advance() {
	switch Step1Robot.Dir {
	case N:
		Step1Robot.Y++
	case E:
		Step1Robot.X++
	case S:
		Step1Robot.Y--
	case W:
		Step1Robot.X--
	default:
		log.Fatalf("unrecognized direction %d", Step1Robot.Dir)
	}
}

func (d Dir) String() string {
	switch d {
	case N:
		return "N"
	case E:
		return "E"
	case S:
		return "S"
	case W:
		return "W"
	default:
		return fmt.Sprintf("unrecognized direction %d", d)
	}
}

// Step 2
// Define Action type here.
type Action struct{}

func StartRobot(command chan Command, action chan Action) {
	panic("Please implement the StartRobot function")
}

func Room(extent Rect, robot Step2Robot, action chan Action, report chan Step2Robot) {
	panic("Please implement the Room function")
}

// Step 3
// Define Action3 type here.
type Action3 struct{}

func StartRobot3(name, script string, action chan Action3, log chan string) {
	panic("Please implement the StartRobot3 function")
}

func Room3(extent Rect, robots []Step3Robot, action chan Action3, rep chan []Step3Robot, log chan string) {
	panic("Please implement the Room3 function")
}
<|endoftext|>


<commit_before>package cache

type SubscriptionInterface interface {
	Each(f func(item interface{}) bool) error
	Subscribe(routingKeyPrefix string) error
	Unsubscribe(routingKeyPrefix string) error
	Has(routingKeyPrefix string) (bool, error)
	Len() (int, error)
}

type SubscriptionStorage struct {
	storage SubscriptionInterface
}

func NewStorage(typeOf, socketID string) (*SubscriptionStorage, error) {

	var err error
	var be SubscriptionInterface

	switch typeOf {
	case "redis":
		be, err = NewRedis(socketID)
	default:
		be, err = NewSubscriptionSet(socketID)
	}

	if err != nil {
		return nil, err
	}

	return &SubscriptionStorage{
		storage: be,
	}, nil

}

func (s *SubscriptionStorage) Each(f func(item interface{}) bool) error {
	return s.storage.Each(f)
}

func (s *SubscriptionStorage) Subscribe(routingKeyPrefix string) error {
	return s.storage.Subscribe(routingKeyPrefix)
}
func (s *SubscriptionStorage) Unsubscribe(routingKeyPrefix string) error {
	return s.storage.Unsubscribe(routingKeyPrefix)
}

func (s *SubscriptionStorage) Has(routingKeyPrefix string) (bool, error) {
	return s.storage.Has(routingKeyPrefix)
}

func (s *SubscriptionStorage) Len() (int, error) {
	return s.storage.Len()
}
<commit_msg>Broker: change parameter name<commit_after>package cache

type SubscriptionInterface interface {
	Each(f func(item interface{}) bool) error
	Subscribe(routingKeyPrefix string) error
	Unsubscribe(routingKeyPrefix string) error
	Has(routingKeyPrefix string) (bool, error)
	Len() (int, error)
}

type SubscriptionStorage struct {
	storage SubscriptionInterface
}

func NewStorage(cacheType, socketID string) (*SubscriptionStorage, error) {

	var err error
	var be SubscriptionInterface

	switch cacheType {
	case "redis":
		be, err = NewRedis(socketID)
	default:
		be, err = NewSubscriptionSet(socketID)
	}

	if err != nil {
		return nil, err
	}

	return &SubscriptionStorage{
		storage: be,
	}, nil

}

func (s *SubscriptionStorage) Each(f func(item interface{}) bool) error {
	return s.storage.Each(f)
}

func (s *SubscriptionStorage) Subscribe(routingKeyPrefix string) error {
	return s.storage.Subscribe(routingKeyPrefix)
}
func (s *SubscriptionStorage) Unsubscribe(routingKeyPrefix string) error {
	return s.storage.Unsubscribe(routingKeyPrefix)
}

func (s *SubscriptionStorage) Has(routingKeyPrefix string) (bool, error) {
	return s.storage.Has(routingKeyPrefix)
}

func (s *SubscriptionStorage) Len() (int, error) {
	return s.storage.Len()
}
<|endoftext|>