<commit_before>package fire

import (
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
	"gopkg.in/mgo.v2"
)

// An Application provides an out-of-the-box configuration of components to
// get started with building JSON APIs.
type Application struct {
	set       *Set
	router    *echo.Echo
	bodyLimit string

	disableCompression bool
	disableRecovery    bool
}

// New creates and returns a new Application.
func New(mongoURI, prefix string) *Application {
	// create router
	router := echo.New()

	// connect to database
	sess, err := mgo.Dial(mongoURI)
	if err != nil {
		panic(err)
	}

	set := NewSet(sess, router, prefix)

	return &Application{
		set:       set,
		router:    router,
		bodyLimit: "4K",
	}
}

// EnableCORS will enable CORS with a general configuration.
//
// Note: You can always add your own CORS middleware to the router.
func (a *Application) EnableCORS(origins ...string) {
	a.router.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: origins,
		// TODO: Allow "Accept, Cache-Control"?
		AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderAuthorization,
			echo.HeaderContentType, echo.HeaderXHTTPMethodOverride},
	}))
}

// Mount will add controllers to the set and register them on the router.
//
// Note: Each controller should only be mounted once.
func (a *Application) Mount(controllers ...*Controller) {
	a.set.Mount(controllers...)
}

// Router will return the internally used echo instance.
func (a *Application) Router() *echo.Echo {
	return a.router
}

// EnableMethodOverriding will enable the usage of the X-HTTP-Method-Override
// header to set a request method when using the POST method.
func (a *Application) EnableMethodOverriding() {
	a.router.Pre(middleware.MethodOverride())
}

// SetBodyLimit can be used to override the default body limit of 4K with a new
// value in the form of 4K, 2M, 1G or 1P.
func (a *Application) SetBodyLimit(size string) {
	a.bodyLimit = size
}

// DisableCompression will turn of gzip compression.
//
// Note: This method must be called before calling Run or Start.
func (a *Application) DisableCompression() {
	a.disableCompression = true
}

// DisableRecovery will disable the automatic recover mechanism.
//
// Note: This method must be called before calling Run or Start.
func (a *Application) DisableRecovery() {
	a.disableRecovery = true
}

// Run will run the application using the passed server.
func (a *Application) Run(server engine.Server) {
	// set body limit
	a.router.Use(middleware.BodyLimit(a.bodyLimit))

	// enable gzip compression
	if !a.disableCompression {
		a.router.Use(middleware.Gzip())
	}

	// enable automatic recovery
	if !a.disableRecovery {
		a.router.Use(middleware.Recover())
	}

	a.router.Run(server)
}

// Start will run the application on the specified address.
func (a *Application) Start(addr string) {
	a.Run(standard.New(addr))
}
<commit_msg>make it a setter<commit_after>package fire

import (
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
	"gopkg.in/mgo.v2"
)

// An Application provides an out-of-the-box configuration of components to
// get started with building JSON APIs.
type Application struct {
	set       *Set
	router    *echo.Echo
	bodyLimit string

	enableMethodOverriding bool
	disableCompression     bool
	disableRecovery        bool
}

// New creates and returns a new Application.
func New(mongoURI, prefix string) *Application {
	// create router
	router := echo.New()

	// connect to database
	sess, err := mgo.Dial(mongoURI)
	if err != nil {
		panic(err)
	}

	set := NewSet(sess, router, prefix)

	return &Application{
		set:       set,
		router:    router,
		bodyLimit: "4K",
	}
}

// EnableCORS will enable CORS with a general configuration.
//
// Note: You can always add your own CORS middleware to the router.
func (a *Application) EnableCORS(origins ...string) {
	a.router.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: origins,
		// TODO: Allow "Accept, Cache-Control"?
		AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderAuthorization,
			echo.HeaderContentType, echo.HeaderXHTTPMethodOverride},
	}))
}

// Mount will add controllers to the set and register them on the router.
//
// Note: Each controller should only be mounted once.
func (a *Application) Mount(controllers ...*Controller) {
	a.set.Mount(controllers...)
}

// Router will return the internally used echo instance.
func (a *Application) Router() *echo.Echo {
	return a.router
}

// EnableMethodOverriding will enable the usage of the X-HTTP-Method-Override
// header to set a request method when using the POST method.
func (a *Application) EnableMethodOverriding() {
	a.enableMethodOverriding = true
}

// SetBodyLimit can be used to override the default body limit of 4K with a new
// value in the form of 4K, 2M, 1G or 1P.
func (a *Application) SetBodyLimit(size string) {
	a.bodyLimit = size
}

// DisableCompression will turn of gzip compression.
//
// Note: This method must be called before calling Run or Start.
func (a *Application) DisableCompression() {
	a.disableCompression = true
}

// DisableRecovery will disable the automatic recover mechanism.
//
// Note: This method must be called before calling Run or Start.
func (a *Application) DisableRecovery() {
	a.disableRecovery = true
}

// Run will run the application using the passed server.
func (a *Application) Run(server engine.Server) {
	// set body limit
	a.router.Use(middleware.BodyLimit(a.bodyLimit))

	if a.enableMethodOverriding {
		a.router.Pre(middleware.MethodOverride())
	}

	// enable gzip compression
	if !a.disableCompression {
		a.router.Use(middleware.Gzip())
	}

	// enable automatic recovery
	if !a.disableRecovery {
		a.router.Use(middleware.Recover())
	}

	a.router.Run(server)
}

// Start will run the application on the specified address.
func (a *Application) Start(addr string) {
	a.Run(standard.New(addr))
}
<|endoftext|>


<commit_before>// Copyright 2018 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 value provides functionality for wrapping Go values to implement
// protoreflect values.
package value

import (
	"fmt"
	"reflect"

	papi "github.com/golang/protobuf/protoapi"
	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
)

// Unwrapper unwraps the value to the underlying value.
// This is implemented by List and Map.
type Unwrapper interface {
	ProtoUnwrap() interface{}
}

var (
	boolType    = reflect.TypeOf(bool(false))
	int32Type   = reflect.TypeOf(int32(0))
	int64Type   = reflect.TypeOf(int64(0))
	uint32Type  = reflect.TypeOf(uint32(0))
	uint64Type  = reflect.TypeOf(uint64(0))
	float32Type = reflect.TypeOf(float32(0))
	float64Type = reflect.TypeOf(float64(0))
	stringType  = reflect.TypeOf(string(""))
	bytesType   = reflect.TypeOf([]byte(nil))

	enumIfaceV2    = reflect.TypeOf((*pref.ProtoEnum)(nil)).Elem()
	messageIfaceV1 = reflect.TypeOf((*papi.Message)(nil)).Elem()
	messageIfaceV2 = reflect.TypeOf((*pref.ProtoMessage)(nil)).Elem()

	byteType = reflect.TypeOf(byte(0))
)

// NewConverter matches a Go type with a protobuf kind and returns a Converter
// that converts between the two. NewConverter panics if it unable to provide a
// conversion between the two. The Converter methods also panic when they are
// called on incorrect Go types.
//
// This matcher deliberately supports a wider range of Go types than what
// protoc-gen-go historically generated to be able to automatically wrap some
// v1 messages generated by other forks of protoc-gen-go.
func NewConverter(t reflect.Type, k pref.Kind) Converter {
	return NewLegacyConverter(t, k, nil)
}

// LegacyWrapper is a set of wrapper methods that wraps legacy v1 Go types
// to implement the v2 reflection APIs.
type (
	LegacyWrapper interface {
		EnumOf(interface{}) LegacyEnum
		EnumTypeOf(interface{}) pref.EnumType

		MessageOf(interface{}) LegacyMessage
		MessageTypeOf(interface{}) pref.MessageType

		ExtensionTypeOf(pref.ExtensionDescriptor, interface{}) pref.ExtensionType

		// TODO: Remove these eventually. See the TODOs in protoapi.
		ExtensionDescFromType(pref.ExtensionType) *papi.ExtensionDesc
		ExtensionTypeFromDesc(*papi.ExtensionDesc) pref.ExtensionType
	}

	LegacyEnum = interface {
		pref.Enum
		ProtoUnwrap() interface{}
	}

	LegacyMessage = interface {
		pref.Message
		ProtoUnwrap() interface{}
	}
)

// NewLegacyConverter is identical to NewConverter,
// but supports wrapping legacy v1 messages to implement the v2 message API
// using the provided LegacyWrapper.
func NewLegacyConverter(t reflect.Type, k pref.Kind, w LegacyWrapper) Converter {
	switch k {
	case pref.BoolKind:
		if t.Kind() == reflect.Bool {
			return makeScalarConverter(t, boolType)
		}
	case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
		if t.Kind() == reflect.Int32 {
			return makeScalarConverter(t, int32Type)
		}
	case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
		if t.Kind() == reflect.Int64 {
			return makeScalarConverter(t, int64Type)
		}
	case pref.Uint32Kind, pref.Fixed32Kind:
		if t.Kind() == reflect.Uint32 {
			return makeScalarConverter(t, uint32Type)
		}
	case pref.Uint64Kind, pref.Fixed64Kind:
		if t.Kind() == reflect.Uint64 {
			return makeScalarConverter(t, uint64Type)
		}
	case pref.FloatKind:
		if t.Kind() == reflect.Float32 {
			return makeScalarConverter(t, float32Type)
		}
	case pref.DoubleKind:
		if t.Kind() == reflect.Float64 {
			return makeScalarConverter(t, float64Type)
		}
	case pref.StringKind:
		if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
			return makeScalarConverter(t, stringType)
		}
	case pref.BytesKind:
		if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
			return makeScalarConverter(t, bytesType)
		}
	case pref.EnumKind:
		// Handle v2 enums, which must satisfy the proto.Enum interface.
		if t.Kind() != reflect.Ptr && t.Implements(enumIfaceV2) {
			et := reflect.Zero(t).Interface().(pref.ProtoEnum).ProtoReflect().Type()
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					e := v.Interface().(pref.ProtoEnum)
					return pref.ValueOf(e.ProtoReflect().Number())
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					rv := reflect.ValueOf(et.New(v.Enum()))
					if rv.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
					}
					return rv
				},
				EnumType: et,
			}
		}

		// Handle v1 enums, which we identify as simply a named int32 type.
		if w != nil && t.PkgPath() != "" && t.Kind() == reflect.Int32 {
			et := w.EnumTypeOf(reflect.Zero(t).Interface())
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					return pref.ValueOf(pref.EnumNumber(v.Int()))
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					return reflect.ValueOf(v.Enum()).Convert(t)
				},
				EnumType: et,
				IsLegacy: true,
			}
		}
	case pref.MessageKind, pref.GroupKind:
		// Handle v2 messages, which must satisfy the proto.Message interface.
		if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV2) {
			mt := reflect.Zero(t).Interface().(pref.ProtoMessage).ProtoReflect().Type()
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					return pref.ValueOf(v.Interface())
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					rv := reflect.ValueOf(v.Message().Interface())
					if rv.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
					}
					return rv
				},
				MessageType: mt,
			}
		}

		// Handle v1 messages, which we need to wrap as a v2 message.
		if w != nil && t.Kind() == reflect.Ptr && t.Implements(messageIfaceV1) {
			mt := w.MessageTypeOf(reflect.Zero(t).Interface())
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					return pref.ValueOf(w.MessageOf(v.Interface()))
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					rv := reflect.ValueOf(v.Message().(Unwrapper).ProtoUnwrap())
					if rv.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
					}
					return rv
				},
				MessageType: mt,
				IsLegacy:    true,
			}
		}
	}
	panic(fmt.Sprintf("invalid Go type %v for protobuf kind %v", t, k))
}

func makeScalarConverter(goType, pbType reflect.Type) Converter {
	return Converter{
		PBValueOf: func(v reflect.Value) pref.Value {
			if v.Type() != goType {
				panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), goType))
			}
			if goType.Kind() == reflect.String && pbType.Kind() == reflect.Slice && v.Len() == 0 {
				return pref.ValueOf([]byte(nil)) // ensure empty string is []byte(nil)
			}
			return pref.ValueOf(v.Convert(pbType).Interface())
		},
		GoValueOf: func(v pref.Value) reflect.Value {
			rv := reflect.ValueOf(v.Interface())
			if rv.Type() != pbType {
				panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), pbType))
			}
			if pbType.Kind() == reflect.String && goType.Kind() == reflect.Slice && rv.Len() == 0 {
				return reflect.Zero(goType) // ensure empty string is []byte(nil)
			}
			return rv.Convert(goType)
		},
	}
}

// Converter provides functions for converting to/from Go reflect.Value types
// and protobuf protoreflect.Value types.
type Converter struct {
	PBValueOf   func(reflect.Value) pref.Value
	GoValueOf   func(pref.Value) reflect.Value
	EnumType    pref.EnumType
	MessageType pref.MessageType
	IsLegacy    bool
}
<commit_msg>internal/value: bugfix for v2 message conversion<commit_after>// Copyright 2018 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 value provides functionality for wrapping Go values to implement
// protoreflect values.
package value

import (
	"fmt"
	"reflect"

	papi "github.com/golang/protobuf/protoapi"
	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
)

// Unwrapper unwraps the value to the underlying value.
// This is implemented by List and Map.
type Unwrapper interface {
	ProtoUnwrap() interface{}
}

var (
	boolType    = reflect.TypeOf(bool(false))
	int32Type   = reflect.TypeOf(int32(0))
	int64Type   = reflect.TypeOf(int64(0))
	uint32Type  = reflect.TypeOf(uint32(0))
	uint64Type  = reflect.TypeOf(uint64(0))
	float32Type = reflect.TypeOf(float32(0))
	float64Type = reflect.TypeOf(float64(0))
	stringType  = reflect.TypeOf(string(""))
	bytesType   = reflect.TypeOf([]byte(nil))

	enumIfaceV2    = reflect.TypeOf((*pref.ProtoEnum)(nil)).Elem()
	messageIfaceV1 = reflect.TypeOf((*papi.Message)(nil)).Elem()
	messageIfaceV2 = reflect.TypeOf((*pref.ProtoMessage)(nil)).Elem()

	byteType = reflect.TypeOf(byte(0))
)

// NewConverter matches a Go type with a protobuf kind and returns a Converter
// that converts between the two. NewConverter panics if it unable to provide a
// conversion between the two. The Converter methods also panic when they are
// called on incorrect Go types.
//
// This matcher deliberately supports a wider range of Go types than what
// protoc-gen-go historically generated to be able to automatically wrap some
// v1 messages generated by other forks of protoc-gen-go.
func NewConverter(t reflect.Type, k pref.Kind) Converter {
	return NewLegacyConverter(t, k, nil)
}

// LegacyWrapper is a set of wrapper methods that wraps legacy v1 Go types
// to implement the v2 reflection APIs.
type (
	LegacyWrapper interface {
		EnumOf(interface{}) LegacyEnum
		EnumTypeOf(interface{}) pref.EnumType

		MessageOf(interface{}) LegacyMessage
		MessageTypeOf(interface{}) pref.MessageType

		ExtensionTypeOf(pref.ExtensionDescriptor, interface{}) pref.ExtensionType

		// TODO: Remove these eventually. See the TODOs in protoapi.
		ExtensionDescFromType(pref.ExtensionType) *papi.ExtensionDesc
		ExtensionTypeFromDesc(*papi.ExtensionDesc) pref.ExtensionType
	}

	LegacyEnum = interface {
		pref.Enum
		ProtoUnwrap() interface{}
	}

	LegacyMessage = interface {
		pref.Message
		ProtoUnwrap() interface{}
	}
)

// NewLegacyConverter is identical to NewConverter,
// but supports wrapping legacy v1 messages to implement the v2 message API
// using the provided LegacyWrapper.
func NewLegacyConverter(t reflect.Type, k pref.Kind, w LegacyWrapper) Converter {
	switch k {
	case pref.BoolKind:
		if t.Kind() == reflect.Bool {
			return makeScalarConverter(t, boolType)
		}
	case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
		if t.Kind() == reflect.Int32 {
			return makeScalarConverter(t, int32Type)
		}
	case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
		if t.Kind() == reflect.Int64 {
			return makeScalarConverter(t, int64Type)
		}
	case pref.Uint32Kind, pref.Fixed32Kind:
		if t.Kind() == reflect.Uint32 {
			return makeScalarConverter(t, uint32Type)
		}
	case pref.Uint64Kind, pref.Fixed64Kind:
		if t.Kind() == reflect.Uint64 {
			return makeScalarConverter(t, uint64Type)
		}
	case pref.FloatKind:
		if t.Kind() == reflect.Float32 {
			return makeScalarConverter(t, float32Type)
		}
	case pref.DoubleKind:
		if t.Kind() == reflect.Float64 {
			return makeScalarConverter(t, float64Type)
		}
	case pref.StringKind:
		if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
			return makeScalarConverter(t, stringType)
		}
	case pref.BytesKind:
		if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
			return makeScalarConverter(t, bytesType)
		}
	case pref.EnumKind:
		// Handle v2 enums, which must satisfy the proto.Enum interface.
		if t.Kind() != reflect.Ptr && t.Implements(enumIfaceV2) {
			et := reflect.Zero(t).Interface().(pref.ProtoEnum).ProtoReflect().Type()
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					e := v.Interface().(pref.ProtoEnum)
					return pref.ValueOf(e.ProtoReflect().Number())
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					rv := reflect.ValueOf(et.New(v.Enum()))
					if rv.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
					}
					return rv
				},
				EnumType: et,
			}
		}

		// Handle v1 enums, which we identify as simply a named int32 type.
		if w != nil && t.PkgPath() != "" && t.Kind() == reflect.Int32 {
			et := w.EnumTypeOf(reflect.Zero(t).Interface())
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					return pref.ValueOf(pref.EnumNumber(v.Int()))
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					return reflect.ValueOf(v.Enum()).Convert(t)
				},
				EnumType: et,
				IsLegacy: true,
			}
		}
	case pref.MessageKind, pref.GroupKind:
		// Handle v2 messages, which must satisfy the proto.Message interface.
		if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV2) {
			mt := reflect.Zero(t).Interface().(pref.ProtoMessage).ProtoReflect().Type()
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					return pref.ValueOf(v.Interface().(pref.ProtoMessage).ProtoReflect())
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					rv := reflect.ValueOf(v.Message().Interface())
					if rv.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
					}
					return rv
				},
				MessageType: mt,
			}
		}

		// Handle v1 messages, which we need to wrap as a v2 message.
		if w != nil && t.Kind() == reflect.Ptr && t.Implements(messageIfaceV1) {
			mt := w.MessageTypeOf(reflect.Zero(t).Interface())
			return Converter{
				PBValueOf: func(v reflect.Value) pref.Value {
					if v.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), t))
					}
					return pref.ValueOf(w.MessageOf(v.Interface()))
				},
				GoValueOf: func(v pref.Value) reflect.Value {
					rv := reflect.ValueOf(v.Message().(Unwrapper).ProtoUnwrap())
					if rv.Type() != t {
						panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), t))
					}
					return rv
				},
				MessageType: mt,
				IsLegacy:    true,
			}
		}
	}
	panic(fmt.Sprintf("invalid Go type %v for protobuf kind %v", t, k))
}

func makeScalarConverter(goType, pbType reflect.Type) Converter {
	return Converter{
		PBValueOf: func(v reflect.Value) pref.Value {
			if v.Type() != goType {
				panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), goType))
			}
			if goType.Kind() == reflect.String && pbType.Kind() == reflect.Slice && v.Len() == 0 {
				return pref.ValueOf([]byte(nil)) // ensure empty string is []byte(nil)
			}
			return pref.ValueOf(v.Convert(pbType).Interface())
		},
		GoValueOf: func(v pref.Value) reflect.Value {
			rv := reflect.ValueOf(v.Interface())
			if rv.Type() != pbType {
				panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), pbType))
			}
			if pbType.Kind() == reflect.String && goType.Kind() == reflect.Slice && rv.Len() == 0 {
				return reflect.Zero(goType) // ensure empty string is []byte(nil)
			}
			return rv.Convert(goType)
		},
	}
}

// Converter provides functions for converting to/from Go reflect.Value types
// and protobuf protoreflect.Value types.
type Converter struct {
	PBValueOf   func(reflect.Value) pref.Value
	GoValueOf   func(pref.Value) reflect.Value
	EnumType    pref.EnumType
	MessageType pref.MessageType
	IsLegacy    bool
}
<|endoftext|>


<commit_before>package epub_test

import (
	"fmt"
	"log"

	"github.com/bmaupin/go-epub"
)

func ExampleEpub_AddCSS() {
	e := epub.NewEpub("My title")

	// Add CSS
	css1Path, err := e.AddCSS("cover.css", "epub.css")
	if err != nil {
		log.Fatal(err)
	}

	// The filename is optional
	css2Path, err := e.AddCSS("cover.css", "")
	if err != nil {
		log.Fatal(err)
	}

	// Use the CSS in a section
	sectionBody := `
Section 1

This is a paragraph.
`
	e.AddSection(sectionBody, "Section 1", "", css1Path)

	fmt.Println(css1Path)
	fmt.Println(css2Path)

	// Output:
	// ../css/epub.css
	// ../css/cover.css
}

func ExampleEpub_AddFont() {
	e := epub.NewEpub("My title")

	// Add a font from a local file
	font1Path, err := e.AddFont("testdata/redacted-script-regular.ttf", "font.ttf")
	if err != nil {
		log.Fatal(err)
	}

	// The filename is optional
	font2Path, err := e.AddFont("testdata/redacted-script-regular.ttf", "")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(font1Path)
	fmt.Println(font2Path)

	// Output:
	// ../fonts/font.ttf
	// ../fonts/redacted-script-regular.ttf
}

func ExampleEpub_AddImage() {
	e := epub.NewEpub("My title")

	// Add an image from a local file
	img1Path, err := e.AddImage("testdata/gophercolor16x16.png", "go-gopher.png")
	if err != nil {
		log.Fatal(err)
	}

	// Add an image from a URL. The filename is optional
	img2Path, err := e.AddImage("https://golang.org/doc/gopher/gophercolor16x16.png", "")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(img1Path)
	fmt.Println(img2Path)

	// Output:
	// ../images/go-gopher.png
	// ../images/gophercolor16x16.png
}

func ExampleEpub_AddSection() {
	e := epub.NewEpub("My title")

	// Add a section. The CSS path is optional
	section1Body := `
Section 1

This is a paragraph.
`
	section1Path, err := e.AddSection(section1Body, "Section 1", "firstsection.xhtml", "")
	if err != nil {
		log.Fatal(err)
	}

	// Link to the first section
	section2Body := fmt.Sprintf(`
Section 2

	Link to section 1`,
		section1Path)
	// The title and filename are also optional
	section2Path, err := e.AddSection(section2Body, "", "", "")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(section1Path)
	fmt.Println(section2Path)

	// Output:
	// firstsection.xhtml
	// section0002.xhtml
}

func ExampleEpub_SetCover() {
	e := epub.NewEpub("My title")

	// Set the cover. The CSS content is optional
	e.SetCover("testdata/gophercolor16x16.png", "")

	// Update the cover using custom CSS
	coverCSSContent := `h1 {
  text-align: center;
}`
	e.SetCover("testdata/gophercolor16x16.png", coverCSSContent)
}
<commit_msg>Update example tests<commit_after>package epub_test

import (
	"fmt"
	"log"

	"github.com/bmaupin/go-epub"
)

func ExampleEpub_AddCSS() {
	e := epub.NewEpub("My title")

	// Add CSS
	css1Path, err := e.AddCSS("cover.css", "epub.css")
	if err != nil {
		log.Fatal(err)
	}

	// The filename is optional
	css2Path, err := e.AddCSS("cover.css", "")
	if err != nil {
		log.Fatal(err)
	}

	// Use the CSS in a section
	sectionBody := `
Section 1

This is a paragraph.
`
	e.AddSection(sectionBody, "Section 1", "", css1Path)

	fmt.Println(css1Path)
	fmt.Println(css2Path)

	// Output:
	// ../css/epub.css
	// ../css/cover.css
}

func ExampleEpub_AddFont() {
	e := epub.NewEpub("My title")

	// Add a font from a local file
	font1Path, err := e.AddFont("testdata/redacted-script-regular.ttf", "font.ttf")
	if err != nil {
		log.Fatal(err)
	}

	// The filename is optional
	font2Path, err := e.AddFont("testdata/redacted-script-regular.ttf", "")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(font1Path)
	fmt.Println(font2Path)

	// Output:
	// ../fonts/font.ttf
	// ../fonts/redacted-script-regular.ttf
}

func ExampleEpub_AddImage() {
	e := epub.NewEpub("My title")

	// Add an image from a local file
	img1Path, err := e.AddImage("testdata/gophercolor16x16.png", "go-gopher.png")
	if err != nil {
		log.Fatal(err)
	}

	// Add an image from a URL. The filename is optional
	img2Path, err := e.AddImage("https://golang.org/doc/gopher/gophercolor16x16.png", "")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(img1Path)
	fmt.Println(img2Path)

	// Output:
	// ../images/go-gopher.png
	// ../images/gophercolor16x16.png
}

func ExampleEpub_AddSection() {
	e := epub.NewEpub("My title")

	// Add a section. The CSS path is optional
	section1Body := `
Section 1

This is a paragraph.
`
	section1Path, err := e.AddSection(section1Body, "Section 1", "firstsection.xhtml", "")
	if err != nil {
		log.Fatal(err)
	}

	// Link to the first section
	section2Body := fmt.Sprintf(`
Section 2

	Link to section 1`,
		section1Path)
	// The title and filename are also optional
	section2Path, err := e.AddSection(section2Body, "", "", "")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(section1Path)
	fmt.Println(section2Path)

	// Output:
	// firstsection.xhtml
	// section0002.xhtml
}

func ExampleEpub_SetCover() {
	e := epub.NewEpub("My title")

	// Set the cover. The CSS file is optional
	err := e.SetCover("testdata/gophercolor16x16.png", "")
	if err != nil {
		log.Fatal(err)
	}

	// Update the cover using custom CSS
	err = e.SetCover("testdata/gophercolor16x16.png", "cover.css")
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package web

import (
	"context"
	"crypto/tls"
	"errors"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

var (
	_app  *Application
	_once sync.Once
)

// Callback function
type Callback func(ctx *Context)

// PanicCallback function
type PanicCallback func(http.ResponseWriter, *http.Request, interface{})

// Application is type of a web.Application
type Application struct {
	trees       map[string]*node
	middlewares Middlewares
	logger      *log.Logger
	panic       PanicCallback
	paramsPool  sync.Pool
	maxParams   uint16
}

// Create return a singleton web.Application
func Create() *Application {
	_once.Do(func() {
		_app = newApplication()
	})
	return _app
}

// newApplication return a web.Application
func newApplication() *Application {
	app := &Application{
		middlewares: Middlewares{},
		logger:      log.New(os.Stdout, "", log.Ldate|log.Ltime),
	}
	return app
}

// SetLogger set Logger
func (app *Application) SetLogger(logger *log.Logger) {
	app.logger = logger
}

// SetPanic set Logger
func (app *Application) SetPanic(panic PanicCallback) {
	app.panic = panic
}

// Use Add the given callback function to this application.middlewares.
func (app *Application) Use(path string, callback Callback) {

	m := Middleware{
		Path:     cleanPath(path),
		Callback: callback,
	}

	app.middlewares = append(app.middlewares, m)
}

// Resource map controller path
func (app *Application) Resource(path string, controller Controller) {
	app.ResourceFn(path, controller, nil)
}

// ResourceFn map controller path and wrap fn
func (app *Application) ResourceFn(path string, controller Controller, fn func(cb Callback, keys ...string) Callback, keys ...string) {

	path = cleanPath(path)

	if fn == nil {
		app.Get(path, controller.Index)
		app.Post(path, controller.Create)
		app.Get(path+":id", controller.Detail)
		app.Patch(path+":id", controller.Update)
		app.Put(path+":id", controller.Update)
		app.Delete(path+":id", controller.Destroy)
	} else {
		app.Get(path, fn(controller.Index, keys...))
		app.Post(path, fn(controller.Create, keys...))
		app.Get(path+":id", fn(controller.Detail, keys...))
		app.Patch(path+":id", fn(controller.Update, keys...))
		app.Put(path+":id", fn(controller.Update, keys...))
		app.Delete(path+":id", fn(controller.Destroy, keys...))
	}
}

// On add event
func (app *Application) On(name string, cb Callback) {

}

// Get method
func (app *Application) Get(path string, cb Callback) {
	app.addRoute(http.MethodGet, path, cb)
}

// Post method
func (app *Application) Post(path string, cb Callback) {
	app.addRoute(http.MethodPost, path, cb)
}

// Put method
func (app *Application) Put(path string, cb Callback) {
	app.addRoute(http.MethodPut, path, cb)
}

// Patch method
func (app *Application) Patch(path string, cb Callback) {
	app.addRoute(http.MethodPatch, path, cb)
}

// Delete method
func (app *Application) Delete(path string, cb Callback) {
	app.addRoute(http.MethodDelete, path, cb)
}

// Options method
func (app *Application) Options(path string, cb Callback) {
	app.addRoute(http.MethodOptions, path, cb)
}

func (app *Application) addRoute(method, path string, cb Callback) {

	if method == "" {
		panic("method must not be empty")
	}

	if len(path) < 1 || path[0] != '/' {
		panic("path must begin with '/' in path '" + path + "'")
	}

	if cb == nil {
		panic("callback must not be nil")
	}

	if app.trees == nil {
		app.trees = make(map[string]*node)
	}

	root := app.trees[method]

	if root == nil {
		root = new(node)
		app.trees[method] = root
	}

	root.addRoute(path, cb)

	if pc := countParams(path); pc > app.maxParams {
		app.maxParams = pc
	}

	if app.paramsPool.New == nil && app.maxParams > 0 {
		app.paramsPool.New = func() interface{} {
			ps := make(Params, 0, app.maxParams)
			return &ps
		}
	}
}

// ServeHTTP
func (app *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	defer app.recv(w, r)
	path := r.URL.Path

	if root := app.trees[r.Method]; root != nil {

		if callback, params, tsr := root.getValue(path, app.getParams); callback != nil {

			ctx := newContext(w, r, params)
			app.putParams(params)

			app.middlewares.exec(path, ctx)

			runTime := time.Now()
			callback(ctx)
			endTime := time.Now()

			app.logf("%s %s %s %s %s", r.Method, path, endTime.Sub(startTime), runTime.Sub(startTime), endTime.Sub(runTime))

			return

		} else if r.Method != http.MethodConnect && path != "/" {

			code := http.StatusMovedPermanently

			if r.Method != http.MethodGet {
				code = http.StatusPermanentRedirect
			}

			if tsr {

				if len(path) > 1 && path[len(path)-1] == '/' {
					r.URL.Path = path[:len(path)-1]
				} else {
					r.URL.Path = path + "/"
				}

				http.Redirect(w, r, r.URL.String(), code)

				return
			}
		}
	}

	http.NotFound(w, r)
}

// ListenAndServe Serve with options on addr
func (app *Application) ListenAndServe(addr string, fns ...func(*http.Server)) error {

	l, err := net.Listen("tcp", addr)

	if err != nil {
		log.Fatal("Listen:", err)
	}

	defer l.Close()

	return app.serve(addr, l, fns...)
}

// ListenAndServeTLS Serve with tls and options on addr
func (app *Application) ListenAndServeTLS(addr string, tlsConfig *tls.Config, fns ...func(*http.Server)) error {

	l, err := tls.Listen("tcp", addr, tlsConfig)

	if err != nil {
		log.Fatal("Listen:", err)
	}

	defer l.Close()

	return app.serve(addr, l, fns...)
}

func (app *Application) serve(addr string, listener net.Listener, fns ...func(*http.Server)) error {

	mux := http.NewServeMux()

	mux.Handle("/", app)

	srv := &http.Server{
		Handler: mux,
	}

	for _, fn := range fns {
		fn(srv)
	}

	defer func() {
		err := srv.Close()
		if err != nil {
			app.logf("srv: %v", err)
		}
	}()

	idleConnsClosed := make(chan struct{})

	go func() {
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt, syscall.SIGTERM)
		<-sigint

		if err := srv.Shutdown(context.Background()); err != nil {
			app.logf("web.go: %v", err)
		}

		close(idleConnsClosed)
	}()

	app.logf("web.go(%d) %s", os.Getpid(), listener.Addr())

	if err := srv.Serve(listener); err != nil {
		app.logf("web.go: %v", err)
	}

	<-idleConnsClosed

	return errors.New("web.go: exit")
}

// Inspect method
func (app *Application) Inspect() string {
	return ""
}

func (app *Application) logf(format string, v ...interface{}) {

	if app.logger != nil {
		app.logger.Printf(format, v...)
	} else {
		log.Printf(format, v...)
	}
}

func (app *Application) getParams() *Params {
	ps := app.paramsPool.Get().(*Params)
	*ps = (*ps)[0:0] // reset slice
	return ps
}

func (app *Application) putParams(ps *Params) {
	if ps != nil {
		app.paramsPool.Put(ps)
	}
}

func (app *Application) recv(w http.ResponseWriter, r *http.Request) {
	if rcv := recover(); rcv != nil {
		if app.panic != nil {
			app.panic(w, r, rcv)
		} else {
			app.logf("web.go: %v", rcv)
		}
	}
}
<commit_msg>change keys to key<commit_after>package web

import (
	"context"
	"crypto/tls"
	"errors"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

var (
	_app  *Application
	_once sync.Once
)

// Callback function
type Callback func(ctx *Context)

// PanicCallback function
type PanicCallback func(http.ResponseWriter, *http.Request, interface{})

// Application is type of a web.Application
type Application struct {
	trees       map[string]*node
	middlewares Middlewares
	logger      *log.Logger
	panic       PanicCallback
	paramsPool  sync.Pool
	maxParams   uint16
}

// Create return a singleton web.Application
func Create() *Application {
	_once.Do(func() {
		_app = newApplication()
	})
	return _app
}

// newApplication return a web.Application
func newApplication() *Application {
	app := &Application{
		middlewares: Middlewares{},
		logger:      log.New(os.Stdout, "", log.Ldate|log.Ltime),
	}
	return app
}

// SetLogger set Logger
func (app *Application) SetLogger(logger *log.Logger) {
	app.logger = logger
}

// SetPanic set Logger
func (app *Application) SetPanic(panic PanicCallback) {
	app.panic = panic
}

// Use Add the given callback function to this application.middlewares.
func (app *Application) Use(path string, callback Callback) {

	m := Middleware{
		Path:     cleanPath(path),
		Callback: callback,
	}

	app.middlewares = append(app.middlewares, m)
}

// Resource map controller path
func (app *Application) Resource(path string, controller Controller) {
	app.ResourceFn(path, controller, nil, "")
}

// ResourceFn map controller path and wrap fn
func (app *Application) ResourceFn(path string, controller Controller, fn func(cb Callback, keys ...string) Callback, key string) {

	path = cleanPath(path)

	if fn == nil {
		app.Get(path, controller.Index)
		app.Post(path, controller.Create)
		app.Get(path+":id", controller.Detail)
		app.Patch(path+":id", controller.Update)
		app.Put(path+":id", controller.Update)
		app.Delete(path+":id", controller.Destroy)
	} else {
		app.Get(path, fn(controller.Index, key+".all", key+".self"))
		app.Post(path, fn(controller.Create, key+".edit"))
		app.Get(path+":id", fn(controller.Detail, key+".all", key+".self"))
		app.Patch(path+":id", fn(controller.Update, key+".edit"))
		app.Put(path+":id", fn(controller.Update, key+".edit"))
		app.Delete(path+":id", fn(controller.Destroy, key+".edit"))
	}
}

// On add event
func (app *Application) On(name string, cb Callback) {

}

// Get method
func (app *Application) Get(path string, cb Callback) {
	app.addRoute(http.MethodGet, path, cb)
}

// Post method
func (app *Application) Post(path string, cb Callback) {
	app.addRoute(http.MethodPost, path, cb)
}

// Put method
func (app *Application) Put(path string, cb Callback) {
	app.addRoute(http.MethodPut, path, cb)
}

// Patch method
func (app *Application) Patch(path string, cb Callback) {
	app.addRoute(http.MethodPatch, path, cb)
}

// Delete method
func (app *Application) Delete(path string, cb Callback) {
	app.addRoute(http.MethodDelete, path, cb)
}

// Options method
func (app *Application) Options(path string, cb Callback) {
	app.addRoute(http.MethodOptions, path, cb)
}

func (app *Application) addRoute(method, path string, cb Callback) {

	if method == "" {
		panic("method must not be empty")
	}

	if len(path) < 1 || path[0] != '/' {
		panic("path must begin with '/' in path '" + path + "'")
	}

	if cb == nil {
		panic("callback must not be nil")
	}

	if app.trees == nil {
		app.trees = make(map[string]*node)
	}

	root := app.trees[method]

	if root == nil {
		root = new(node)
		app.trees[method] = root
	}

	root.addRoute(path, cb)

	if pc := countParams(path); pc > app.maxParams {
		app.maxParams = pc
	}

	if app.paramsPool.New == nil && app.maxParams > 0 {
		app.paramsPool.New = func() interface{} {
			ps := make(Params, 0, app.maxParams)
			return &ps
		}
	}
}

// ServeHTTP
func (app *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	defer app.recv(w, r)
	path := r.URL.Path

	if root := app.trees[r.Method]; root != nil {

		if callback, params, tsr := root.getValue(path, app.getParams); callback != nil {

			ctx := newContext(w, r, params)
			app.putParams(params)

			app.middlewares.exec(path, ctx)

			runTime := time.Now()
			callback(ctx)
			endTime := time.Now()

			app.logf("%s %s %s %s %s", r.Method, path, endTime.Sub(startTime), runTime.Sub(startTime), endTime.Sub(runTime))

			return

		} else if r.Method != http.MethodConnect && path != "/" {

			code := http.StatusMovedPermanently

			if r.Method != http.MethodGet {
				code = http.StatusPermanentRedirect
			}

			if tsr {

				if len(path) > 1 && path[len(path)-1] == '/' {
					r.URL.Path = path[:len(path)-1]
				} else {
					r.URL.Path = path + "/"
				}

				http.Redirect(w, r, r.URL.String(), code)

				return
			}
		}
	}

	http.NotFound(w, r)
}

// ListenAndServe Serve with options on addr
func (app *Application) ListenAndServe(addr string, fns ...func(*http.Server)) error {

	l, err := net.Listen("tcp", addr)

	if err != nil {
		log.Fatal("Listen:", err)
	}

	defer l.Close()

	return app.serve(addr, l, fns...)
}

// ListenAndServeTLS Serve with tls and options on addr
func (app *Application) ListenAndServeTLS(addr string, tlsConfig *tls.Config, fns ...func(*http.Server)) error {

	l, err := tls.Listen("tcp", addr, tlsConfig)

	if err != nil {
		log.Fatal("Listen:", err)
	}

	defer l.Close()

	return app.serve(addr, l, fns...)
}

func (app *Application) serve(addr string, listener net.Listener, fns ...func(*http.Server)) error {

	mux := http.NewServeMux()

	mux.Handle("/", app)

	srv := &http.Server{
		Handler: mux,
	}

	for _, fn := range fns {
		fn(srv)
	}

	defer func() {
		err := srv.Close()
		if err != nil {
			app.logf("srv: %v", err)
		}
	}()

	idleConnsClosed := make(chan struct{})

	go func() {
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt, syscall.SIGTERM)
		<-sigint

		if err := srv.Shutdown(context.Background()); err != nil {
			app.logf("web.go: %v", err)
		}

		close(idleConnsClosed)
	}()

	app.logf("web.go(%d) %s", os.Getpid(), listener.Addr())

	if err := srv.Serve(listener); err != nil {
		app.logf("web.go: %v", err)
	}

	<-idleConnsClosed

	return errors.New("web.go: exit")
}

// Inspect method
func (app *Application) Inspect() string {
	return ""
}

func (app *Application) logf(format string, v ...interface{}) {

	if app.logger != nil {
		app.logger.Printf(format, v...)
	} else {
		log.Printf(format, v...)
	}
}

func (app *Application) getParams() *Params {
	ps := app.paramsPool.Get().(*Params)
	*ps = (*ps)[0:0] // reset slice
	return ps
}

func (app *Application) putParams(ps *Params) {
	if ps != nil {
		app.paramsPool.Put(ps)
	}
}

func (app *Application) recv(w http.ResponseWriter, r *http.Request) {
	if rcv := recover(); rcv != nil {
		if app.panic != nil {
			app.panic(w, r, rcv)
		} else {
			app.logf("web.go: %v", rcv)
		}
	}
}
<|endoftext|>


<commit_before>package scalyr

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strconv"
	"time"
)

var _config Config
var _scalyrEventsWrapper scalyrEventsWrapper
var _scalyrEvents []scalyrEvent

type Application interface {
	Event(sev Severity, attributes interface{})
}

type app struct {
	config Config
}

//
// event should accept Severity ( 0 - 6 ??, 3 being info:  and a message :  and 1 or more additional attributes)
// The "sev" (severity) field should range from 0 to 6, and identifies the importance of this event, using the
//  classic scale "finest, finer, fine, info, warning, error, fatal". This field is optional (defaults to 3 / info).
//
func (app *app) Event(sev Severity, attributes interface{}) {
	//Print(message)
	//Print(string(sev))

	se := &scalyrEvent{
		TS:    strconv.FormatInt(time.Now().UnixNano(), 10),
		Type:  0,
		Sev:   int(sev),
		Attrs: attributes,
	}

	if _scalyrEvents == nil {

		_scalyrEvents = make([]scalyrEvent, 1)
		_scalyrEvents[0] = *se

	} else {
		_scalyrEvents = append(_scalyrEvents, *se)
	}

}

//
// returns a new config struct configured with values...
//
func NewApplication(config Config) Application {

	_config = config

	a := &app{}

	initialize()

	start()

	return a
}

func initialize() {
	si := &scalyrSessionInfo{
		ServerType: "server type here TODO replace this...",
		ServerId:   _APPLICATION_HOSTNAME,
	}

	_scalyrEventsWrapper = scalyrEventsWrapper{
		Token:       _config.ScalyrEventWriteKey,
		Session:     _APPLICATION_PROCESS_ID,
		SessionInfo: *si,
		Events:      nil,
	}

	Print("Events wrapper created: ", _scalyrEventsWrapper)
}

func start() {

	go func() {
		for range ticker.C {
			flush()
		}
	}()

}

func flush() {
	Print("Flushing events NOW. ", nil)

	_scalyrEventsWrapper.Events = _scalyrEvents

	json, _ := json.Marshal(_scalyrEventsWrapper)

	Print("Events being sent to Scalyr: ", string(json))
	//fmt.Println(string(json))

	url := _SCALYR_ADDEVENTS_ENDPOINT

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	Print("Status that came back from Scalyr: ", resp.Status)

	//fmt.Println("response Status:", resp.Status)
	//fmt.Println("response Headers:", resp.Header)
	//body, _ := ioutil.ReadAll(resp.Body)
	//fmt.Println("response Body:", string(body))
}
<commit_msg>error changes<commit_after>package scalyr

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strconv"
	"time"
)

var _config Config
var _scalyrEventsWrapper scalyrEventsWrapper
var _scalyrEvents []scalyrEvent

type Application interface {
	Event(sev Severity, attributes interface{})
}

type app struct {
	config Config
}

//
// event should accept Severity ( 0 - 6 ??, 3 being info:  and a message :  and 1 or more additional attributes)
// The "sev" (severity) field should range from 0 to 6, and identifies the importance of this event, using the
//  classic scale "finest, finer, fine, info, warning, error, fatal". This field is optional (defaults to 3 / info).
//
func (app *app) Event(sev Severity, attributes interface{}) {

	se := &scalyrEvent{
		TS:    strconv.FormatInt(time.Now().UnixNano(), 10),
		Type:  0,
		Sev:   int(sev),
		Attrs: attributes,
	}

	if _scalyrEvents == nil {

		_scalyrEvents = make([]scalyrEvent, 1)
		_scalyrEvents[0] = *se

	} else {
		_scalyrEvents = append(_scalyrEvents, *se)
	}

}

//
// returns a new config struct configured with values...
//
func NewApplication(config Config) Application {

	_config = config

	a := &app{}

	initialize()

	start()

	return a
}

func initialize() {
	si := &scalyrSessionInfo{
		ServerType: "server type here TODO replace this...",
		ServerId:   _APPLICATION_HOSTNAME,
	}

	_scalyrEventsWrapper = scalyrEventsWrapper{
		Token:       _config.ScalyrEventWriteKey,
		Session:     _APPLICATION_PROCESS_ID,
		SessionInfo: *si,
		Events:      nil,
	}

	Print("Events wrapper created: ", _scalyrEventsWrapper)
}

func start() {

	go func() {
		for range ticker.C {
			flush()
		}
	}()

}

func flush() {
	Print("Flushing events NOW. ", nil)

	_scalyrEventsWrapper.Events = _scalyrEvents

	json, _ := json.Marshal(_scalyrEventsWrapper)

	Print("Events being sent to Scalyr: ", string(json))
	//fmt.Println(string(json))

	url := _SCALYR_ADDEVENTS_ENDPOINT

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		//panic(err)
		Print("ERROR trying to POST to Scalyr API:", err)
	}
	defer resp.Body.Close()

	Print("Status that came back from Scalyr: ", resp.Status)

	//fmt.Println("response Status:", resp.Status)
	//fmt.Println("response Headers:", resp.Header)
	//body, _ := ioutil.ReadAll(resp.Body)
	//fmt.Println("response Body:", string(body))
}
<|endoftext|>


<commit_before>package hostpool

import (
	"github.com/bitly/go-hostpool"
)

func ExampleNewEpsilonGreedy() {
	hp := hostpool.NewEpsilonGreedy([]string{"a", "b"}, 0, &hostpool.LinearEpsilonValueCalculator{})
	hostResponse := hp.Get()
	hostname := hostResponse.Host()
	err := nil // (make a request with hostname)
	hostResponse.Mark(err)
}
<commit_msg>Fix import cycle and build error<commit_after>package hostpool_test

import (
	"github.com/bitly/go-hostpool"
)

func ExampleNewEpsilonGreedy() {
	hp := hostpool.NewEpsilonGreedy([]string{"a", "b"}, 0, &hostpool.LinearEpsilonValueCalculator{})
	hostResponse := hp.Get()
	_ = hostResponse.Host()
	hostResponse.Mark(nil)
}
<|endoftext|>


<commit_before>package refmt_test

import (
	"bytes"
	"fmt"

	"github.com/polydawn/refmt"
	"github.com/polydawn/refmt/obj/atlas"
)

func ExampleJsonEncodeDefaults() {
	type MyType struct {
		X string
		Y int
	}

	MyType_AtlasEntry := atlas.BuildEntry(MyType{}).
		StructMap().Autogenerate().
		Complete()

	atl := atlas.MustBuild(
		MyType_AtlasEntry,
		// this is a vararg... stack more entries here!
	)

	var buf bytes.Buffer
	encoder := refmt.NewAtlasedJsonEncoder(&buf, atl)
	err := encoder.Marshal(MyType{"a", 1})
	fmt.Println(buf.String())
	fmt.Printf("%v\n", err)

	// Output:
	// {"x":"a","y":1}
	// <nil>
}
<commit_msg>Add example of building your own struct mapping atlas, with details.<commit_after>package refmt_test

import (
	"bytes"
	"fmt"

	"github.com/polydawn/refmt"
	"github.com/polydawn/refmt/obj/atlas"
)

func ExampleJsonEncodeAtlasDefaults() {
	type MyType struct {
		X string
		Y int
	}

	MyType_AtlasEntry := atlas.BuildEntry(MyType{}).
		StructMap().Autogenerate().
		Complete()

	atl := atlas.MustBuild(
		MyType_AtlasEntry,
		// this is a vararg... stack more entries here!
	)

	var buf bytes.Buffer
	encoder := refmt.NewAtlasedJsonEncoder(&buf, atl)
	err := encoder.Marshal(MyType{"a", 1})
	fmt.Println(buf.String())
	fmt.Printf("%v\n", err)

	// Output:
	// {"x":"a","y":1}
	// <nil>
}

func ExampleJsonEncodeAtlasCustom() {
	type MyType struct {
		X string
		Y int
	}

	MyType_AtlasEntry := atlas.BuildEntry(MyType{}).
		StructMap().
		AddField("X", atlas.StructMapEntry{SerialName: "overrideName"}).
		// and no "Y" mapping at all!
		Complete()

	atl := atlas.MustBuild(
		MyType_AtlasEntry,
		// this is a vararg... stack more entries here!
	)

	var buf bytes.Buffer
	encoder := refmt.NewAtlasedJsonEncoder(&buf, atl)
	err := encoder.Marshal(MyType{"a", 1})
	fmt.Println(buf.String())
	fmt.Printf("%v\n", err)

	// Output:
	// {"overrideName":"a"}
	// <nil>
}
<|endoftext|>


<commit_before>package upcloud

import (
	"fmt"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
	"testing"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestUpcloudFirewallRules_basic(t *testing.T) {
	var providers []*schema.Provider

	var firewallRules upcloud.FirewallRules
	resourceName := "upcloud_firewall_rules.my_server"

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { testAccPreCheck(t) },
		ProviderFactories: testAccProviderFactories(&providers),
		CheckDestroy:      testAccCheckFirewallRulesDestroy,
		Steps: []resource.TestStep{
			{
				Config: testUpcloudFirewallRulesInstanceConfig(),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "firewall_rule.#", "1"),
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
					testAccCheckUpCloudFirewallRuleAttributes(&firewallRules, 0, "accept",
						"Allow SSH from this network",
						"IPv4",
						"",
						"tcp",
						"in",
						"",
						"",
						"22",
						"22",
						"192.168.1.1",
						"192.168.1.255",
						"",
						""),
				),
			},
		},
	})
}

func TestUpcloudFirewallRules_update(t *testing.T) {
	var providers []*schema.Provider

	var firewallRules upcloud.FirewallRules
	resourceName := "upcloud_firewall_rules.my_server"

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { testAccPreCheck(t) },
		ProviderFactories: testAccProviderFactories(&providers),
		CheckDestroy:      testAccCheckFirewallRulesDestroy,
		Steps: []resource.TestStep{
			{
				Config: testUpcloudFirewallRulesInstanceConfig(),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "firewall_rule.#", "1"),
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
				),
			},
			{
				Config: testUpcloudFirewallRulesInstanceConfig_update(),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "firewall_rule.#", "2"),
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
				),
			},
		},
	})
}

func TestUpcloudFirewallRules_import(t *testing.T) {
	var providers []*schema.Provider

	var firewallRules upcloud.FirewallRules
	resourceName := "upcloud_firewall_rules.my_server"

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { testAccPreCheck(t) },
		ProviderFactories: testAccProviderFactories(&providers),
		CheckDestroy:      testAccCheckFirewallRulesDestroy,
		Steps: []resource.TestStep{
			{
				Config: testUpcloudFirewallRulesInstanceConfig(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})

}

func testAccCheckFirewallRulesDestroy(s *terraform.State) error {

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "upcloud_firewall_rules" {
			continue
		}

		client := testAccProvider.Meta().(*service.Service)
		firewallRules, err := client.GetFirewallRules(&request.GetFirewallRulesRequest{
			ServerUUID: rs.Primary.ID,
		})
		if err != nil {
			return fmt.Errorf("[WARN] Error listing firewall rules when deleting upcloud firewall rules (%s): %s", rs.Primary.ID, err)
		}

		if len(firewallRules.FirewallRules) != 0 {
			return fmt.Errorf("[WARN] Error  %d firewall rules found against server (%s)", len(firewallRules.FirewallRules), rs.Primary.ID)
		}

	}
	return nil
}

func testAccCheckFirewallRulesExists(resourceName string, firewallRules *upcloud.FirewallRules) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Look for the full resource name and error if not found
		rs, ok := s.RootModule().Resources[resourceName]
		if !ok {
			return fmt.Errorf("Not found: %s", resourceName)
		}

		// The provider has not set the ID for the resource
		if rs.Primary.ID == "" {
			return fmt.Errorf("No Firewall ID is set")
		}

		client := testAccProvider.Meta().(*service.Service)
		latest, err := client.GetFirewallRules(&request.GetFirewallRulesRequest{
			ServerUUID: rs.Primary.ID,
		})

		if err != nil {
			return err
		}

		// Update the reference the remote located storage
		*firewallRules = *latest

		return nil
	}
}

func testAccCheckUpCloudFirewallRuleAttributes(firewallRules *upcloud.FirewallRules, index int, action, comment, family, icmpType, protocol, direction, destination_address_start, destination_address_end, destination_port_start, destination_port_end, source_address_start, source_address_end, source_port_start, source_port_end string) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		firewallRule := firewallRules.FirewallRules[index]

		if firewallRule.Action != action {
			return fmt.Errorf("Bad action, expected (%s), got (%s)", action, firewallRule.Action)
		}

		if firewallRule.Comment != comment {
			return fmt.Errorf("Bad comment, expected (%s), got (%s)", comment, firewallRule.Comment)
		}

		if firewallRule.Family != family {
			return fmt.Errorf("Bad family, expected (%s), got (%s)", family, firewallRule.Family)
		}

		if firewallRule.ICMPType != icmpType {
			return fmt.Errorf("Bad icmpType, expected (%s), got (%s)", icmpType, firewallRule.ICMPType)
		}

		if firewallRule.Protocol != protocol {
			return fmt.Errorf("Bad protocol, expected (%s), got (%s)", protocol, firewallRule.Protocol)
		}

		if firewallRule.Direction != direction {
			return fmt.Errorf("Bad direction, expected (%s), got (%s)", direction, firewallRule.Direction)
		}

		if firewallRule.DestinationAddressStart != destination_address_start {
			return fmt.Errorf("Bad destination_address_start, expected (%s), got (%s)", destination_address_start, firewallRule.DestinationAddressStart)
		}

		if firewallRule.DestinationAddressEnd != destination_address_end {
			return fmt.Errorf("Bad destination_address_end, expected (%s), got (%s)", destination_address_end, firewallRule.DestinationAddressEnd)
		}

		if firewallRule.DestinationPortStart != destination_port_start {
			return fmt.Errorf("Bad destination_port_start, expected (%s), got (%s)", destination_port_start, firewallRule.DestinationPortStart)
		}

		if firewallRule.DestinationPortEnd != destination_port_end {
			return fmt.Errorf("Bad destination_port_end, expected (%s), got (%s)", destination_port_end, firewallRule.DestinationPortEnd)
		}

		if firewallRule.SourceAddressStart != source_address_start {
			return fmt.Errorf("Bad source_address_start, expected (%s), got (%s)", source_address_start, firewallRule.SourceAddressStart)
		}

		if firewallRule.SourceAddressEnd != source_address_end {
			return fmt.Errorf("Bad source_address_end, expected (%s), got (%s)", source_address_end, firewallRule.SourceAddressEnd)
		}

		if firewallRule.SourcePortStart != source_port_start {
			return fmt.Errorf("Bad source_port_start, expected (%s), got (%s)", source_port_start, firewallRule.SourcePortStart)
		}

		if firewallRule.SourcePortEnd != source_port_end {
			return fmt.Errorf("Bad source_port_end, expected (%s), got (%s)", source_port_end, firewallRule.SourcePortEnd)
		}

		return nil
	}
}

func testUpcloudFirewallRulesInstanceConfig() string {
	return fmt.Sprintf(`
		resource "upcloud_server" "my_server" {
		  zone     = "fi-hel1"
		  hostname = "debian.example.com"
		  plan     = "1xCPU-2GB"

		  template {
			storage = "01000000-0000-4000-8000-000020050100"
			size = 10
		  }

		  network_interface {
			type = "utility"
		  }

		}

		resource "upcloud_firewall_rules" "my_server" {
		  server_id = upcloud_server.my_server.id

		  firewall_rule {
			action = "accept"
			comment = "Allow SSH from this network"
			destination_address_end = ""
			destination_address_start = ""
			destination_port_end = 22
			destination_port_start = 22
			direction = "in"
			family = "IPv4"
			icmp_type = ""
			protocol = "tcp"
			source_address_end = "192.168.1.255"
			source_address_start = "192.168.1.1"
		  }

		}`)
}

func testUpcloudFirewallRulesInstanceConfig_update() string {
	return fmt.Sprintf(`
		resource "upcloud_server" "my_server" {
		  zone     = "fi-hel1"
		  hostname = "debian.example.com"
		  plan     = "1xCPU-2GB"

		  template {
			storage = "01000000-0000-4000-8000-000020050100"
			size = 10
		  }

		  network_interface {
			type = "utility"
		  }

		}

		resource "upcloud_firewall_rules" "my_server" {
		  server_id = upcloud_server.my_server.id

		  firewall_rule {
			action = "accept"
			comment = "Allow SSH from this network"
			destination_address_end = ""
			destination_address_start = ""
			destination_port_end = 22
			destination_port_start = 22
			direction = "in"
			family = "IPv4"
			icmp_type = ""
			protocol = "tcp"
			source_address_end = "192.168.1.255"
			source_address_start = "192.168.1.1"
		  }

		  firewall_rule {
			action = "accept"
			comment = "Allow SSH from this network"
			destination_address_end = ""
			destination_address_start = ""
			destination_port_end = 22
			destination_port_start = 22
			direction = "in"
			family = "IPv4"
			icmp_type = ""
			protocol = "tcp"
			source_address_end = "192.168.3.255"
			source_address_start = "192.168.3.1"
		  }

		}`)
}
<commit_msg>fix(test/firewall): fix check logic<commit_after>package upcloud

import (
	"fmt"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
	"testing"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestUpcloudFirewallRules_basic(t *testing.T) {
	var providers []*schema.Provider

	var firewallRules upcloud.FirewallRules
	resourceName := "upcloud_firewall_rules.my_server"

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { testAccPreCheck(t) },
		ProviderFactories: testAccProviderFactories(&providers),
		CheckDestroy:      testAccCheckFirewallRulesDestroy,
		Steps: []resource.TestStep{
			{
				Config: testUpcloudFirewallRulesInstanceConfig(),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "firewall_rule.#", "1"),
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
					testAccCheckUpCloudFirewallRuleAttributes(&firewallRules, 0, "accept",
						"Allow SSH from this network",
						"IPv4",
						"",
						"tcp",
						"in",
						"",
						"",
						"22",
						"22",
						"192.168.1.1",
						"192.168.1.255",
						"",
						""),
				),
			},
		},
	})
}

func TestUpcloudFirewallRules_update(t *testing.T) {
	var providers []*schema.Provider

	var firewallRules upcloud.FirewallRules
	resourceName := "upcloud_firewall_rules.my_server"

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { testAccPreCheck(t) },
		ProviderFactories: testAccProviderFactories(&providers),
		CheckDestroy:      testAccCheckFirewallRulesDestroy,
		Steps: []resource.TestStep{
			{
				Config: testUpcloudFirewallRulesInstanceConfig(),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "firewall_rule.#", "1"),
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
				),
			},
			{
				Config: testUpcloudFirewallRulesInstanceConfig_update(),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "firewall_rule.#", "2"),
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
				),
			},
		},
	})
}

func TestUpcloudFirewallRules_import(t *testing.T) {
	var providers []*schema.Provider

	var firewallRules upcloud.FirewallRules
	resourceName := "upcloud_firewall_rules.my_server"

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { testAccPreCheck(t) },
		ProviderFactories: testAccProviderFactories(&providers),
		CheckDestroy:      testAccCheckFirewallRulesDestroy,
		Steps: []resource.TestStep{
			{
				Config: testUpcloudFirewallRulesInstanceConfig(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckFirewallRulesExists(resourceName, &firewallRules),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})

}

func testAccCheckFirewallRulesDestroy(s *terraform.State) error {

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "upcloud_firewall_rules" {
			continue
		}

		client := testAccProvider.Meta().(*service.Service)

		_, err := client.GetFirewallRules(&request.GetFirewallRulesRequest{
			ServerUUID: rs.Primary.ID,
		})
		if err == nil {
			return fmt.Errorf(
				"Error firewall rules still exists after deletion for server (%s)",
				rs.Primary.ID,
			)
		}

	}
	return nil
}

func testAccCheckFirewallRulesExists(resourceName string, firewallRules *upcloud.FirewallRules) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Look for the full resource name and error if not found
		rs, ok := s.RootModule().Resources[resourceName]
		if !ok {
			return fmt.Errorf("Not found: %s", resourceName)
		}

		// The provider has not set the ID for the resource
		if rs.Primary.ID == "" {
			return fmt.Errorf("No Firewall ID is set")
		}

		client := testAccProvider.Meta().(*service.Service)
		latest, err := client.GetFirewallRules(&request.GetFirewallRulesRequest{
			ServerUUID: rs.Primary.ID,
		})

		if err != nil {
			return err
		}

		// Update the reference the remote located storage
		*firewallRules = *latest

		return nil
	}
}

func testAccCheckUpCloudFirewallRuleAttributes(firewallRules *upcloud.FirewallRules, index int, action, comment, family, icmpType, protocol, direction, destination_address_start, destination_address_end, destination_port_start, destination_port_end, source_address_start, source_address_end, source_port_start, source_port_end string) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		firewallRule := firewallRules.FirewallRules[index]

		if firewallRule.Action != action {
			return fmt.Errorf("Bad action, expected (%s), got (%s)", action, firewallRule.Action)
		}

		if firewallRule.Comment != comment {
			return fmt.Errorf("Bad comment, expected (%s), got (%s)", comment, firewallRule.Comment)
		}

		if firewallRule.Family != family {
			return fmt.Errorf("Bad family, expected (%s), got (%s)", family, firewallRule.Family)
		}

		if firewallRule.ICMPType != icmpType {
			return fmt.Errorf("Bad icmpType, expected (%s), got (%s)", icmpType, firewallRule.ICMPType)
		}

		if firewallRule.Protocol != protocol {
			return fmt.Errorf("Bad protocol, expected (%s), got (%s)", protocol, firewallRule.Protocol)
		}

		if firewallRule.Direction != direction {
			return fmt.Errorf("Bad direction, expected (%s), got (%s)", direction, firewallRule.Direction)
		}

		if firewallRule.DestinationAddressStart != destination_address_start {
			return fmt.Errorf("Bad destination_address_start, expected (%s), got (%s)", destination_address_start, firewallRule.DestinationAddressStart)
		}

		if firewallRule.DestinationAddressEnd != destination_address_end {
			return fmt.Errorf("Bad destination_address_end, expected (%s), got (%s)", destination_address_end, firewallRule.DestinationAddressEnd)
		}

		if firewallRule.DestinationPortStart != destination_port_start {
			return fmt.Errorf("Bad destination_port_start, expected (%s), got (%s)", destination_port_start, firewallRule.DestinationPortStart)
		}

		if firewallRule.DestinationPortEnd != destination_port_end {
			return fmt.Errorf("Bad destination_port_end, expected (%s), got (%s)", destination_port_end, firewallRule.DestinationPortEnd)
		}

		if firewallRule.SourceAddressStart != source_address_start {
			return fmt.Errorf("Bad source_address_start, expected (%s), got (%s)", source_address_start, firewallRule.SourceAddressStart)
		}

		if firewallRule.SourceAddressEnd != source_address_end {
			return fmt.Errorf("Bad source_address_end, expected (%s), got (%s)", source_address_end, firewallRule.SourceAddressEnd)
		}

		if firewallRule.SourcePortStart != source_port_start {
			return fmt.Errorf("Bad source_port_start, expected (%s), got (%s)", source_port_start, firewallRule.SourcePortStart)
		}

		if firewallRule.SourcePortEnd != source_port_end {
			return fmt.Errorf("Bad source_port_end, expected (%s), got (%s)", source_port_end, firewallRule.SourcePortEnd)
		}

		return nil
	}
}

func testUpcloudFirewallRulesInstanceConfig() string {
	return fmt.Sprintf(`
		resource "upcloud_server" "my_server" {
		  zone     = "fi-hel1"
		  hostname = "debian.example.com"
		  plan     = "1xCPU-2GB"

		  template {
			storage = "01000000-0000-4000-8000-000020050100"
			size = 10
		  }

		  network_interface {
			type = "utility"
		  }

		}

		resource "upcloud_firewall_rules" "my_server" {
		  server_id = upcloud_server.my_server.id

		  firewall_rule {
			action = "accept"
			comment = "Allow SSH from this network"
			destination_address_end = ""
			destination_address_start = ""
			destination_port_end = 22
			destination_port_start = 22
			direction = "in"
			family = "IPv4"
			icmp_type = ""
			protocol = "tcp"
			source_address_end = "192.168.1.255"
			source_address_start = "192.168.1.1"
		  }

		}`)
}

func testUpcloudFirewallRulesInstanceConfig_update() string {
	return fmt.Sprintf(`
		resource "upcloud_server" "my_server" {
		  zone     = "fi-hel1"
		  hostname = "debian.example.com"
		  plan     = "1xCPU-2GB"

		  template {
			storage = "01000000-0000-4000-8000-000020050100"
			size = 10
		  }

		  network_interface {
			type = "utility"
		  }

		}

		resource "upcloud_firewall_rules" "my_server" {
		  server_id = upcloud_server.my_server.id

		  firewall_rule {
			action = "accept"
			comment = "Allow SSH from this network"
			destination_address_end = ""
			destination_address_start = ""
			destination_port_end = 22
			destination_port_start = 22
			direction = "in"
			family = "IPv4"
			icmp_type = ""
			protocol = "tcp"
			source_address_end = "192.168.1.255"
			source_address_start = "192.168.1.1"
		  }

		  firewall_rule {
			action = "accept"
			comment = "Allow SSH from this network"
			destination_address_end = ""
			destination_address_start = ""
			destination_port_end = 22
			destination_port_start = 22
			direction = "in"
			family = "IPv4"
			icmp_type = ""
			protocol = "tcp"
			source_address_end = "192.168.3.255"
			source_address_start = "192.168.3.1"
		  }

		}`)
}
<|endoftext|>


<commit_before>package server

import (
	"sync/atomic"

	"github.com/coreos/etcd/clientv3"
	"github.com/golang/protobuf/proto"
	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/kvproto/pkg/msgpb"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/pingcap/kvproto/pkg/raft_cmdpb"
	"github.com/pingcap/kvproto/pkg/raftpb"
	"github.com/pingcap/kvproto/pkg/util"
	"github.com/twinj/uuid"
)

const (
	maxSendRetry = 10
)

func (c *raftCluster) handleAddPeerReq(region *metapb.Region) (*metapb.Peer, error) {
	peerID, err := c.s.idAlloc.Alloc()
	if err != nil {
		return nil, errors.Trace(err)
	}

	mu := &c.mu
	mu.RLock()
	defer mu.RUnlock()

	// Find a proper store which the region has not in.
	// Now we just choose the first store. Later we will do
	// a better choice.
	//
	// TODO:
	// 1, The stores may be in same machine, so we should choose the best
	// store which the region's current stores are not in. We can use IP to
	// check this.
	// 2, We can check the store statistics and find a low load store.
	// 3, more algorithms...
LOOP:
	for _, store := range mu.stores {
		// we can't add peer in the same store.
		for _, peer := range region.Peers {
			if peer.GetStoreId() == store.GetId() {
				continue LOOP
			}
		}
		return &metapb.Peer{
			Id:      proto.Uint64(peerID),
			StoreId: proto.Uint64(store.GetId()),
		}, nil
	}
	return nil, errors.Errorf("find no store to add peer for region %v", region)
}

// If leader is nil, we will return an error, or else we can remove none leader peer.
func (c *raftCluster) handleRemovePeerReq(region *metapb.Region, leaderID uint64) (*metapb.Peer, error) {
	if len(region.Peers) <= 1 {
		return nil, errors.Errorf("can not remove peer for region %v", region)
	}
	for _, peer := range region.Peers {
		if peer.GetId() != leaderID {
			return peer, nil
		}
	}
	// Maybe we can't enter here.
	return nil, errors.Errorf("find no proper peer to remove for region %v", region)
}

func (c *raftCluster) handleChangePeerReq(region *metapb.Region, leaderID uint64) (*pdpb.ChangePeer, error) {
	clusterMeta, err := c.GetConfig()
	if err != nil {
		return nil, errors.Trace(err)
	}

	var (
		maxPeerCount = int(clusterMeta.GetMaxPeerNumber())
		regionID     = region.GetId()
		peerCount    = len(region.GetPeers())
		changeType   raftpb.ConfChangeType
		peer         *metapb.Peer
	)

	if peerCount == maxPeerCount {
		log.Infof("region %d peer count equals %d, no need to change peer", regionID, maxPeerCount)
		return nil, nil
	} else if peerCount < maxPeerCount {
		log.Infof("region %d peer count %d < %d, need to add peer", regionID, peerCount, maxPeerCount)
		changeType = raftpb.ConfChangeType_AddNode
		if peer, err = c.handleAddPeerReq(region); err != nil {
			return nil, errors.Trace(err)
		}
	} else {
		log.Infof("region %d peer count %d > %d, need to remove peer", regionID, peerCount, maxPeerCount)
		changeType = raftpb.ConfChangeType_RemoveNode
		if peer, err = c.handleRemovePeerReq(region, leaderID); err != nil {
			return nil, errors.Trace(err)
		}
	}

	changePeer := &pdpb.ChangePeer{
		ChangeType: changeType.Enum(),
		Peer:       peer,
	}

	return changePeer, nil
}

func (c *raftCluster) maybeChangePeer(request *pdpb.RegionHeartbeatRequest, reqRegion *metapb.Region,
	region *metapb.Region) ([]clientv3.Op, *pdpb.ChangePeer, error) {
	leader := request.GetLeader()
	if leader == nil {
		return nil, nil, errors.Errorf("invalid request leader, %v", request)
	}
	if region == nil {
		return nil, nil, nil
	}

	regionEpoch := region.GetRegionEpoch()
	reqRegionEpoch := reqRegion.GetRegionEpoch()

	if reqRegionEpoch.GetConfVer() < regionEpoch.GetConfVer() {
		// If the request epoch configure version is less than the current one, return an error.
		return nil, nil, errors.Errorf("invalid region epoch, request: %v, currenrt: %v", reqRegionEpoch, regionEpoch)
	} else if reqRegionEpoch.GetConfVer() > regionEpoch.GetConfVer() {
		// If the request epoch configure version is greater than the current one, update region meta.
		regionSearchPath := makeRegionSearchKey(c.clusterRoot, reqRegion.GetEndKey())
		regionValue, err := proto.Marshal(reqRegion)
		if err != nil {
			return nil, nil, errors.Trace(err)
		}

		var ops []clientv3.Op
		ops = append(ops, clientv3.OpPut(regionSearchPath, string(regionValue)))
		return ops, nil, nil
	}

	// If the request epoch configure version is equal to the current one, handle change peer request.
	changePeer, err := c.handleChangePeerReq(reqRegion, leader.GetId())
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return nil, changePeer, nil
}

func (c *raftCluster) HandleAskSplit(request *pdpb.AskSplitRequest) (*pdpb.AskSplitResponse, error) {
	reqRegion := request.GetRegion()
	startKey := reqRegion.GetStartKey()
	region, err := c.GetRegion(startKey)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// If the request epoch is less than current region epoch, then returns an error.
	reqRegionEpoch := reqRegion.GetRegionEpoch()
	regionEpoch := region.GetRegionEpoch()
	if reqRegionEpoch.GetVersion() < regionEpoch.GetVersion() ||
		reqRegionEpoch.GetConfVer() < regionEpoch.GetConfVer() {
		return nil, errors.Errorf("invalid region epoch, request: %v, currenrt: %v", reqRegionEpoch, regionEpoch)
	}

	newRegionID, err := c.s.idAlloc.Alloc()
	if err != nil {
		return nil, errors.Trace(err)
	}

	peerIDs := make([]uint64, len(request.Region.Peers))
	for i := 0; i < len(peerIDs); i++ {
		if peerIDs[i], err = c.s.idAlloc.Alloc(); err != nil {
			return nil, errors.Trace(err)
		}
	}

	split := &pdpb.AskSplitResponse{
		NewRegionId: proto.Uint64(newRegionID),
		NewPeerIds:  peerIDs,
	}

	return split, nil
}

func (c *raftCluster) maybeSplit(request *pdpb.RegionHeartbeatRequest, reqRegion *metapb.Region,
	region *metapb.Region) ([]clientv3.Op, error) {
	// For split, we should handle heartbeat carefully.
	// E.g, for region 1 [a, c) -> 1 [a, b) + 2 [b, c).
	// after split, region 1 and 2 will do heartbeat independently.
	// We can know that now 1 can be found by region id but 2 is not.
	// So we must process the region range overlapped problem.

	var ops []clientv3.Op
	regionValue, err := proto.Marshal(reqRegion)
	if err != nil {
		return nil, errors.Trace(err)
	}
	reqRegionEncStartKey := encodeRegionStartKey(reqRegion.GetStartKey())
	reqRegionEncEndKey := encodeRegionSearchKey(reqRegion.GetEndKey())
	reqRegionPath := makeRegionKey(c.clusterRoot, reqRegion.GetId())
	reqSearchKey := makeRegionSearchKey(c.clusterRoot, reqRegion.GetEndKey())

	if region == nil {
		// Find no range after start key, insert directly.
		ops = append(ops, clientv3.OpPut(reqRegionPath, reqRegionEncEndKey))
		ops = append(ops, clientv3.OpPut(reqSearchKey, string(regionValue)))
		return ops, nil
	}

	// If the request epoch is less than current region epoch, then returns an error.
	reqRegionEpoch := reqRegion.GetRegionEpoch()
	regionEpoch := region.GetRegionEpoch()
	if reqRegionEpoch.GetVersion() < regionEpoch.GetVersion() {
		// If the request epoch version is less than the current one, return an error.
		return nil, errors.Errorf("invalid region epoch, request: %v, currenrt: %v", reqRegionEpoch, regionEpoch)
	} else if reqRegionEpoch.GetVersion() == regionEpoch.GetVersion() {
		// If the request epoch version is equal to the current one, do nothing.
		return nil, nil
	}

	regionEncStartKey := encodeRegionStartKey(region.GetStartKey())
	regionEncEndKey := encodeRegionSearchKey(region.GetEndKey())

	if reqRegionEncStartKey == regionEncStartKey &&
		reqRegionEncEndKey == regionEncEndKey {
		// Seems there is something wrong? Do nothing.
	} else if regionEncStartKey >= reqRegionEncEndKey {
		// No range [start, end) in region now, insert directly.
		ops = append(ops, clientv3.OpPut(reqRegionPath, reqRegionEncEndKey))
		ops = append(ops, clientv3.OpPut(reqSearchKey, string(regionValue)))
	} else {
		// Region overlapped, remove old region, insert new one.
		// E.g, 1 [a, c) -> 1 [a, b) + 2 [b, c), either new 1 or 2 reports, the region
		// is overlapped with origin [a, c).
		regionPath := makeRegionKey(c.clusterRoot, region.GetId())
		regionSearchKey := makeRegionSearchKey(c.clusterRoot, region.GetEndKey())
		if regionPath != reqRegionPath {
			ops = append(ops, clientv3.OpDelete(regionPath))
		}
		if regionSearchKey != reqSearchKey {
			ops = append(ops, clientv3.OpDelete(regionSearchKey))
		}
		ops = append(ops, clientv3.OpPut(reqRegionPath, reqRegionEncEndKey))
		ops = append(ops, clientv3.OpPut(reqSearchKey, string(regionValue)))
	}

	return ops, nil
}

func (c *raftCluster) sendRaftCommand(request *raft_cmdpb.RaftCmdRequest, region *metapb.Region) (*raft_cmdpb.RaftCmdResponse, error) {
	originPeer := request.Header.Peer

RETRY:
	for i := 0; i < maxSendRetry; i++ {
		resp, err := c.callCommand(request)
		if err != nil {
			// We may meet some error, maybe network broken, node down, etc.
			// We can check later next time.
			return nil, errors.Trace(err)
		}

		if resp.Header.Error != nil && resp.Header.Error.NotLeader != nil {
			log.Warnf("peer %v is not leader, we got %v", request.Header.Peer, resp.Header.Error)

			leader := resp.Header.Error.NotLeader.Leader
			if leader != nil {
				// The origin peer is not leader and we get the new leader,
				// send this message to the new leader again.
				request.Header.Peer = leader
				continue
			}

			regionID := region.GetId()
			// The origin peer is not leader, but we can't get the leader now,
			// so we try to get the leader in other region peers.
			for _, peer := range region.Peers {
				if peer.GetId() == originPeer.GetId() {
					continue
				}

				leader, err := c.getRegionLeader(regionID, peer)
				if err != nil {
					log.Errorf("get region %d leader err %v", regionID, err)
					continue
				}
				if leader == nil {
					log.Infof("can not get leader for region %d in peer %v", regionID, peer)
					continue
				}

				// We get leader here.
				request.Header.Peer = leader
				continue RETRY
			}
		}

		return resp, nil
	}

	return nil, errors.Errorf("send raft command %v failed", request)
}

func (c *raftCluster) callCommand(request *raft_cmdpb.RaftCmdRequest) (*raft_cmdpb.RaftCmdResponse, error) {
	storeID := request.Header.Peer.GetStoreId()
	store, err := c.GetStore(storeID)
	if err != nil {
		return nil, errors.Trace(err)
	}

	nc, err := c.storeConns.GetConn(store.GetAddress())
	if err != nil {
		return nil, errors.Trace(err)
	}

	msg := &msgpb.Message{
		MsgType: msgpb.MessageType_Cmd.Enum(),
		CmdReq:  request,
	}

	msgID := atomic.AddUint64(&c.s.msgID, 1)
	if err = util.WriteMessage(nc.conn, msgID, msg); err != nil {
		c.storeConns.RemoveConn(store.GetAddress())
		return nil, errors.Trace(err)
	}

	msg.Reset()
	if _, err = util.ReadMessage(nc.conn, msg); err != nil {
		c.storeConns.RemoveConn(store.GetAddress())
		return nil, errors.Trace(err)
	}

	if msg.CmdResp == nil {
		// This is a very serious bug, should we panic here?
		return nil, errors.Errorf("invalid command response message but %v", msg)
	}

	return msg.CmdResp, nil
}

func (c *raftCluster) getRegionDetail(regionID uint64, peer *metapb.Peer) (*raft_cmdpb.RegionDetailResponse, error) {
	request := &raft_cmdpb.RaftCmdRequest{
		Header: &raft_cmdpb.RaftRequestHeader{
			Uuid:     uuid.NewV4().Bytes(),
			RegionId: proto.Uint64(regionID),
			Peer:     peer,
		},
		StatusRequest: &raft_cmdpb.StatusRequest{
			CmdType:      raft_cmdpb.StatusCmdType_RegionDetail.Enum(),
			RegionDetail: &raft_cmdpb.RegionDetailRequest{},
		},
	}

	resp, err := c.callCommand(request)
	if err != nil {
		return nil, errors.Trace(err)
	}

	if resp.StatusResponse != nil && resp.StatusResponse.RegionDetail != nil {
		return resp.StatusResponse.RegionDetail, nil
	}

	return nil, errors.Errorf("get region %d detail failed, got resp %v", regionID, resp)
}

func (c *raftCluster) getRegionLeader(regionID uint64, peer *metapb.Peer) (*metapb.Peer, error) {
	request := &raft_cmdpb.RaftCmdRequest{
		Header: &raft_cmdpb.RaftRequestHeader{
			Uuid:     uuid.NewV4().Bytes(),
			RegionId: proto.Uint64(regionID),
			Peer:     peer,
		},
		StatusRequest: &raft_cmdpb.StatusRequest{
			CmdType:      raft_cmdpb.StatusCmdType_RegionLeader.Enum(),
			RegionLeader: &raft_cmdpb.RegionLeaderRequest{},
		},
	}

	resp, err := c.callCommand(request)
	if err != nil {
		return nil, errors.Trace(err)
	}

	if resp.StatusResponse != nil && resp.StatusResponse.RegionLeader != nil {
		return resp.StatusResponse.RegionLeader.Leader, nil
	}

	return nil, errors.Errorf("get region %d leader failed, got resp %v", regionID, resp)
}
<commit_msg>server: remove useless code.<commit_after>package server

import (
	"sync/atomic"

	"github.com/coreos/etcd/clientv3"
	"github.com/golang/protobuf/proto"
	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/kvproto/pkg/msgpb"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/pingcap/kvproto/pkg/raft_cmdpb"
	"github.com/pingcap/kvproto/pkg/raftpb"
	"github.com/pingcap/kvproto/pkg/util"
)

func (c *raftCluster) handleAddPeerReq(region *metapb.Region) (*metapb.Peer, error) {
	peerID, err := c.s.idAlloc.Alloc()
	if err != nil {
		return nil, errors.Trace(err)
	}

	mu := &c.mu
	mu.RLock()
	defer mu.RUnlock()

	// Find a proper store which the region has not in.
	// Now we just choose the first store. Later we will do
	// a better choice.
	//
	// TODO:
	// 1, The stores may be in same machine, so we should choose the best
	// store which the region's current stores are not in. We can use IP to
	// check this.
	// 2, We can check the store statistics and find a low load store.
	// 3, more algorithms...
LOOP:
	for _, store := range mu.stores {
		// we can't add peer in the same store.
		for _, peer := range region.Peers {
			if peer.GetStoreId() == store.GetId() {
				continue LOOP
			}
		}
		return &metapb.Peer{
			Id:      proto.Uint64(peerID),
			StoreId: proto.Uint64(store.GetId()),
		}, nil
	}
	return nil, errors.Errorf("find no store to add peer for region %v", region)
}

// If leader is nil, we will return an error, or else we can remove none leader peer.
func (c *raftCluster) handleRemovePeerReq(region *metapb.Region, leaderID uint64) (*metapb.Peer, error) {
	if len(region.Peers) <= 1 {
		return nil, errors.Errorf("can not remove peer for region %v", region)
	}
	for _, peer := range region.Peers {
		if peer.GetId() != leaderID {
			return peer, nil
		}
	}
	// Maybe we can't enter here.
	return nil, errors.Errorf("find no proper peer to remove for region %v", region)
}

func (c *raftCluster) handleChangePeerReq(region *metapb.Region, leaderID uint64) (*pdpb.ChangePeer, error) {
	clusterMeta, err := c.GetConfig()
	if err != nil {
		return nil, errors.Trace(err)
	}

	var (
		maxPeerCount = int(clusterMeta.GetMaxPeerNumber())
		regionID     = region.GetId()
		peerCount    = len(region.GetPeers())
		changeType   raftpb.ConfChangeType
		peer         *metapb.Peer
	)

	if peerCount == maxPeerCount {
		log.Infof("region %d peer count equals %d, no need to change peer", regionID, maxPeerCount)
		return nil, nil
	} else if peerCount < maxPeerCount {
		log.Infof("region %d peer count %d < %d, need to add peer", regionID, peerCount, maxPeerCount)
		changeType = raftpb.ConfChangeType_AddNode
		if peer, err = c.handleAddPeerReq(region); err != nil {
			return nil, errors.Trace(err)
		}
	} else {
		log.Infof("region %d peer count %d > %d, need to remove peer", regionID, peerCount, maxPeerCount)
		changeType = raftpb.ConfChangeType_RemoveNode
		if peer, err = c.handleRemovePeerReq(region, leaderID); err != nil {
			return nil, errors.Trace(err)
		}
	}

	changePeer := &pdpb.ChangePeer{
		ChangeType: changeType.Enum(),
		Peer:       peer,
	}

	return changePeer, nil
}

func (c *raftCluster) maybeChangePeer(request *pdpb.RegionHeartbeatRequest, reqRegion *metapb.Region,
	region *metapb.Region) ([]clientv3.Op, *pdpb.ChangePeer, error) {
	leader := request.GetLeader()
	if leader == nil {
		return nil, nil, errors.Errorf("invalid request leader, %v", request)
	}
	if region == nil {
		return nil, nil, nil
	}

	regionEpoch := region.GetRegionEpoch()
	reqRegionEpoch := reqRegion.GetRegionEpoch()

	if reqRegionEpoch.GetConfVer() < regionEpoch.GetConfVer() {
		// If the request epoch configure version is less than the current one, return an error.
		return nil, nil, errors.Errorf("invalid region epoch, request: %v, currenrt: %v", reqRegionEpoch, regionEpoch)
	} else if reqRegionEpoch.GetConfVer() > regionEpoch.GetConfVer() {
		// If the request epoch configure version is greater than the current one, update region meta.
		regionSearchPath := makeRegionSearchKey(c.clusterRoot, reqRegion.GetEndKey())
		regionValue, err := proto.Marshal(reqRegion)
		if err != nil {
			return nil, nil, errors.Trace(err)
		}

		var ops []clientv3.Op
		ops = append(ops, clientv3.OpPut(regionSearchPath, string(regionValue)))
		return ops, nil, nil
	}

	// If the request epoch configure version is equal to the current one, handle change peer request.
	changePeer, err := c.handleChangePeerReq(reqRegion, leader.GetId())
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return nil, changePeer, nil
}

func (c *raftCluster) HandleAskSplit(request *pdpb.AskSplitRequest) (*pdpb.AskSplitResponse, error) {
	reqRegion := request.GetRegion()
	startKey := reqRegion.GetStartKey()
	region, err := c.GetRegion(startKey)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// If the request epoch is less than current region epoch, then returns an error.
	reqRegionEpoch := reqRegion.GetRegionEpoch()
	regionEpoch := region.GetRegionEpoch()
	if reqRegionEpoch.GetVersion() < regionEpoch.GetVersion() ||
		reqRegionEpoch.GetConfVer() < regionEpoch.GetConfVer() {
		return nil, errors.Errorf("invalid region epoch, request: %v, currenrt: %v", reqRegionEpoch, regionEpoch)
	}

	newRegionID, err := c.s.idAlloc.Alloc()
	if err != nil {
		return nil, errors.Trace(err)
	}

	peerIDs := make([]uint64, len(request.Region.Peers))
	for i := 0; i < len(peerIDs); i++ {
		if peerIDs[i], err = c.s.idAlloc.Alloc(); err != nil {
			return nil, errors.Trace(err)
		}
	}

	split := &pdpb.AskSplitResponse{
		NewRegionId: proto.Uint64(newRegionID),
		NewPeerIds:  peerIDs,
	}

	return split, nil
}

func (c *raftCluster) maybeSplit(request *pdpb.RegionHeartbeatRequest, reqRegion *metapb.Region,
	region *metapb.Region) ([]clientv3.Op, error) {
	// For split, we should handle heartbeat carefully.
	// E.g, for region 1 [a, c) -> 1 [a, b) + 2 [b, c).
	// after split, region 1 and 2 will do heartbeat independently.
	// We can know that now 1 can be found by region id but 2 is not.
	// So we must process the region range overlapped problem.

	var ops []clientv3.Op
	regionValue, err := proto.Marshal(reqRegion)
	if err != nil {
		return nil, errors.Trace(err)
	}
	reqRegionEncStartKey := encodeRegionStartKey(reqRegion.GetStartKey())
	reqRegionEncEndKey := encodeRegionSearchKey(reqRegion.GetEndKey())
	reqRegionPath := makeRegionKey(c.clusterRoot, reqRegion.GetId())
	reqSearchKey := makeRegionSearchKey(c.clusterRoot, reqRegion.GetEndKey())

	if region == nil {
		// Find no range after start key, insert directly.
		ops = append(ops, clientv3.OpPut(reqRegionPath, reqRegionEncEndKey))
		ops = append(ops, clientv3.OpPut(reqSearchKey, string(regionValue)))
		return ops, nil
	}

	// If the request epoch is less than current region epoch, then returns an error.
	reqRegionEpoch := reqRegion.GetRegionEpoch()
	regionEpoch := region.GetRegionEpoch()
	if reqRegionEpoch.GetVersion() < regionEpoch.GetVersion() {
		// If the request epoch version is less than the current one, return an error.
		return nil, errors.Errorf("invalid region epoch, request: %v, currenrt: %v", reqRegionEpoch, regionEpoch)
	} else if reqRegionEpoch.GetVersion() == regionEpoch.GetVersion() {
		// If the request epoch version is equal to the current one, do nothing.
		return nil, nil
	}

	regionEncStartKey := encodeRegionStartKey(region.GetStartKey())
	regionEncEndKey := encodeRegionSearchKey(region.GetEndKey())

	if reqRegionEncStartKey == regionEncStartKey &&
		reqRegionEncEndKey == regionEncEndKey {
		// Seems there is something wrong? Do nothing.
	} else if regionEncStartKey >= reqRegionEncEndKey {
		// No range [start, end) in region now, insert directly.
		ops = append(ops, clientv3.OpPut(reqRegionPath, reqRegionEncEndKey))
		ops = append(ops, clientv3.OpPut(reqSearchKey, string(regionValue)))
	} else {
		// Region overlapped, remove old region, insert new one.
		// E.g, 1 [a, c) -> 1 [a, b) + 2 [b, c), either new 1 or 2 reports, the region
		// is overlapped with origin [a, c).
		regionPath := makeRegionKey(c.clusterRoot, region.GetId())
		regionSearchKey := makeRegionSearchKey(c.clusterRoot, region.GetEndKey())
		if regionPath != reqRegionPath {
			ops = append(ops, clientv3.OpDelete(regionPath))
		}
		if regionSearchKey != reqSearchKey {
			ops = append(ops, clientv3.OpDelete(regionSearchKey))
		}
		ops = append(ops, clientv3.OpPut(reqRegionPath, reqRegionEncEndKey))
		ops = append(ops, clientv3.OpPut(reqSearchKey, string(regionValue)))
	}

	return ops, nil
}

func (c *raftCluster) callCommand(request *raft_cmdpb.RaftCmdRequest) (*raft_cmdpb.RaftCmdResponse, error) {
	storeID := request.Header.Peer.GetStoreId()
	store, err := c.GetStore(storeID)
	if err != nil {
		return nil, errors.Trace(err)
	}

	nc, err := c.storeConns.GetConn(store.GetAddress())
	if err != nil {
		return nil, errors.Trace(err)
	}

	msg := &msgpb.Message{
		MsgType: msgpb.MessageType_Cmd.Enum(),
		CmdReq:  request,
	}

	msgID := atomic.AddUint64(&c.s.msgID, 1)
	if err = util.WriteMessage(nc.conn, msgID, msg); err != nil {
		c.storeConns.RemoveConn(store.GetAddress())
		return nil, errors.Trace(err)
	}

	msg.Reset()
	if _, err = util.ReadMessage(nc.conn, msg); err != nil {
		c.storeConns.RemoveConn(store.GetAddress())
		return nil, errors.Trace(err)
	}

	if msg.CmdResp == nil {
		// This is a very serious bug, should we panic here?
		return nil, errors.Errorf("invalid command response message but %v", msg)
	}

	return msg.CmdResp, nil
}
<|endoftext|>