<commit_before>// +build ignore
//
// This file builds the rotation code: `go run transform/generator.go`

package main

import (
	"fmt"
	"os"
	"text/template"
)

type rotation struct {
	Method         string
	Comment        string
	getDstXBase    string
	GetDstY        string
	DimensionOrder string
}

func valTimesInt(s string, i int) string {
	switch i {
	case 1:
		return s
	case 2:
		return fmt.Sprintf("(%s << 1)", s)
	case 4:
		return fmt.Sprintf("(%s << 2)", s)
	case 8:
		return fmt.Sprintf("(%s << 3)", s)
	default:
		return fmt.Sprintf("(%s * %d)", s, i)
	}
}

func (r rotation) GetSrcX(i int) string {
	return valTimesInt("x", i)
}

func (r rotation) GetDstX(i int) string {
	return valTimesInt(r.getDstXBase, i)
}

var rotate90 rotation = rotation{
	Method:         "Rotate90",
	Comment:        "does a simple 90-degree clockwise rotation",
	getDstXBase:    "(maxY - 1 - y)",
	GetDstY:        "x",
	DimensionOrder: "srcHeight, srcWidth",
}

var rotate180 rotation = rotation{
	Method:         "Rotate180",
	Comment:        "does a simple 180-degree clockwise rotation",
	getDstXBase:    "(maxX - 1 - x)",
	GetDstY:        "(maxY - 1 - y)",
	DimensionOrder: "srcWidth, srcHeight",
}

var rotate270 rotation = rotation{
	Method:         "Rotate270",
	Comment:        "does a simple 270-degree clockwise rotation",
	getDstXBase:    "y",
	GetDstY:        "(maxX - 1 - x)",
	DimensionOrder: "srcHeight, srcWidth",
}

var rotateMirror rotation = rotation{
	Method:         "Mirror",
	Comment:        "flips the image around its vertical axis",
	getDstXBase:    "(maxX - 1 - x)",
	GetDstY:        "y",
	DimensionOrder: "srcWidth, srcHeight",
}

type imageType struct {
	String            string
	Shortstring       string
	ConstructorMethod string
	CopyStatement     string
	ByteSize          int
}

var typeGray = imageType{
	String:            "*image.Gray",
	Shortstring:       "Gray",
	ConstructorMethod: "image.NewGray",
	CopyStatement:     "dstPix[dstIdx] = srcPix[srcIdx]",
	ByteSize:          1,
}

var typeRGBA = imageType{
	String:            "*image.RGBA",
	Shortstring:       "RGBA",
	ConstructorMethod: "image.NewRGBA",
	CopyStatement:     "copy(dstPix[dstIdx:dstIdx+4], srcPix[srcIdx:srcIdx+4])",
	ByteSize:          4,
}

type Page struct {
	Rotations []rotation
	Types     []imageType
}

func main() {
	t := template.Must(template.ParseFiles("transform/template.txt"))
	f, err := os.Create("transform/rotation.go")
	if err != nil {
		fmt.Println("ERROR creating file:", err)
	}

	p := Page{
		Rotations: []rotation{rotate90, rotate180, rotate270, rotateMirror},
		Types:     []imageType{typeGray, typeRGBA},
	}

	err = t.Execute(f, p)
	if err != nil {
		fmt.Println("ERROR:", err)
	}
}
<commit_msg>Fix transform.go's paths<commit_after>// +build ignore
//
// This file builds the rotation code: `go run transform/generator.go`

package main

import (
	"fmt"
	"os"
	"text/template"
)

type rotation struct {
	Method         string
	Comment        string
	getDstXBase    string
	GetDstY        string
	DimensionOrder string
}

func valTimesInt(s string, i int) string {
	switch i {
	case 1:
		return s
	case 2:
		return fmt.Sprintf("(%s << 1)", s)
	case 4:
		return fmt.Sprintf("(%s << 2)", s)
	case 8:
		return fmt.Sprintf("(%s << 3)", s)
	default:
		return fmt.Sprintf("(%s * %d)", s, i)
	}
}

func (r rotation) GetSrcX(i int) string {
	return valTimesInt("x", i)
}

func (r rotation) GetDstX(i int) string {
	return valTimesInt(r.getDstXBase, i)
}

var rotate90 rotation = rotation{
	Method:         "Rotate90",
	Comment:        "does a simple 90-degree clockwise rotation",
	getDstXBase:    "(maxY - 1 - y)",
	GetDstY:        "x",
	DimensionOrder: "srcHeight, srcWidth",
}

var rotate180 rotation = rotation{
	Method:         "Rotate180",
	Comment:        "does a simple 180-degree clockwise rotation",
	getDstXBase:    "(maxX - 1 - x)",
	GetDstY:        "(maxY - 1 - y)",
	DimensionOrder: "srcWidth, srcHeight",
}

var rotate270 rotation = rotation{
	Method:         "Rotate270",
	Comment:        "does a simple 270-degree clockwise rotation",
	getDstXBase:    "y",
	GetDstY:        "(maxX - 1 - x)",
	DimensionOrder: "srcHeight, srcWidth",
}

var rotateMirror rotation = rotation{
	Method:         "Mirror",
	Comment:        "flips the image around its vertical axis",
	getDstXBase:    "(maxX - 1 - x)",
	GetDstY:        "y",
	DimensionOrder: "srcWidth, srcHeight",
}

type imageType struct {
	String            string
	Shortstring       string
	ConstructorMethod string
	CopyStatement     string
	ByteSize          int
}

var typeGray = imageType{
	String:            "*image.Gray",
	Shortstring:       "Gray",
	ConstructorMethod: "image.NewGray",
	CopyStatement:     "dstPix[dstIdx] = srcPix[srcIdx]",
	ByteSize:          1,
}

var typeRGBA = imageType{
	String:            "*image.RGBA",
	Shortstring:       "RGBA",
	ConstructorMethod: "image.NewRGBA",
	CopyStatement:     "copy(dstPix[dstIdx:dstIdx+4], srcPix[srcIdx:srcIdx+4])",
	ByteSize:          4,
}

type Page struct {
	Rotations []rotation
	Types     []imageType
}

func main() {
	t := template.Must(template.ParseFiles("src/transform/template.txt"))
	f, err := os.Create("src/transform/rotation.go")
	if err != nil {
		fmt.Println("ERROR creating file:", err)
	}

	p := Page{
		Rotations: []rotation{rotate90, rotate180, rotate270, rotateMirror},
		Types:     []imageType{typeGray, typeRGBA},
	}

	err = t.Execute(f, p)
	if err != nil {
		fmt.Println("ERROR:", err)
	}
}
<|endoftext|>


<commit_before>package uic

import (
	"encoding/base64"
	"encoding/json"
	"io/ioutil"
	"log"
	"github.com/Cepave/fe/g"
	"github.com/Cepave/fe/http/base"
	. "github.com/Cepave/fe/model/uic"
	"github.com/Cepave/fe/utils"
	"github.com/toolkits/str"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type AuthController struct {
	base.BaseController
}

func (this *AuthController) Logout() {
	u := this.Ctx.Input.GetData("CurrentUser").(*User)
	token := this.Ctx.GetCookie("token")
	if len(token) > 0 {
		url := g.Config().Api.Logout + "/" + token
		log.Println("logout url =", url)
		result := getRequest(url)
		log.Println("logout result =", result)
		this.Ctx.SetCookie("token", "", 0, "/")
		this.Ctx.SetCookie("token", "", 0, "/", ".owlemon.com")
	}
	RemoveSessionByUid(u.Id)
	this.Ctx.SetCookie("sig", "", 0, "/")
	this.Ctx.SetCookie("sig", "", 0, "/", ".owlemon.com")
	this.Redirect("/auth/login", 302)
}

func (this *AuthController) LoginGet() {
	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")

	cookieSig := this.Ctx.GetCookie("sig")
	if cookieSig == "" {
		this.renderLoginPage(appSig, callback)
		return
	}

	sessionObj := ReadSessionBySig(cookieSig)
	if sessionObj == nil {
		this.renderLoginPage(appSig, callback)
		return
	}

	if int64(sessionObj.Expired) < time.Now().Unix() {
		RemoveSessionByUid(sessionObj.Uid)
		this.renderLoginPage(appSig, callback)
		return
	}

	if appSig != "" && callback != "" {
		this.Redirect(callback, 302)
	} else {
		this.Redirect("/me/info", 302)
	}
}

func (this *AuthController) LoginPost() {
	name := this.GetString("name", "")
	password := this.GetString("password", "")

	if name == "" || password == "" {
		this.ServeErrJson("name or password is blank")
		return
	}

	var u *User

	ldapEnabled := this.MustGetBool("ldap", false)

	if ldapEnabled {
		sucess, err := utils.LdapBind(g.Config().Ldap.Addr, name, password)
		if err != nil {
			this.ServeErrJson(err.Error())
			return
		}

		if !sucess {
			this.ServeErrJson("name or password error")
			return
		}

		arr := strings.Split(name, "@")
		var userName, userEmail string
		if len(arr) == 2 {
			userName = arr[0]
			userEmail = name
		} else {
			userName = name
			userEmail = ""
		}

		u = ReadUserByName(userName)
		if u == nil {
			// 说明用户不存在
			u = &User{
				Name:   userName,
				Passwd: "",
				Email:  userEmail,
			}
			_, err = u.Save()
			if err != nil {
				this.ServeErrJson("insert user fail " + err.Error())
				return
			}
		}
	} else {
		u = ReadUserByName(name)
		if u == nil {
			this.ServeErrJson("no such user")
			return
		}

		if u.Passwd != str.Md5Encode(g.Config().Salt+password) {
			this.ServeErrJson("password error")
			return
		}
	}

	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")
	if appSig != "" && callback != "" {
		SaveSessionAttrs(u.Id, appSig, int(time.Now().Unix())+3600*24*30)
	} else {
		this.CreateSession(u.Id, 3600*24*30)
	}

	this.ServeDataJson(callback)
}

func (this *AuthController) renderLoginPage(sig, callback string) {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["LdapEnabled"] = g.Config().Ldap.Enabled
	this.Data["Sig"] = sig
	this.Data["Callback"] = callback
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/login.html"
}

func (this *AuthController) RegisterGet() {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/register.html"
}

func (this *AuthController) RegisterPost() {
	if !g.Config().CanRegister {
		this.ServeErrJson("registration system is not open")
		return
	}

	name := strings.TrimSpace(this.GetString("name", ""))
	password := strings.TrimSpace(this.GetString("password", ""))
	repeatPassword := strings.TrimSpace(this.GetString("repeat_password", ""))

	if password != repeatPassword {
		this.ServeErrJson("password not equal the repeart one")
		return
	}

	if !utils.IsUsernameValid(name) {
		this.ServeErrJson("name pattern is invalid")
		return
	}

	if ReadUserIdByName(name) > 0 {
		this.ServeErrJson("name is already existent")
		return
	}

	lastId, err := InsertRegisterUser(name, str.Md5Encode(g.Config().Salt+password))
	if err != nil {
		this.ServeErrJson("insert user fail " + err.Error())
		return
	}

	this.CreateSession(lastId, 3600*24*30)

	this.ServeOKJson()
}

func (this *AuthController) CreateSession(uid int64, maxAge int) int {
	sig := utils.GenerateUUID()
	expired := int(time.Now().Unix()) + maxAge
	SaveSessionAttrs(uid, sig, expired)
	this.Ctx.SetCookie("sig", sig, maxAge, "/")
	this.Ctx.SetCookie("sig", sig, maxAge, "/", ".owlemon.com")
	return expired
}

/**
 * @function name:   func (this *AuthController) LoginThirdParty()
 * @description:     This function returns third party login URL.
 * @related issues:  OWL-206
 * @param:           void
 * @return:          void
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       beego.Router("/auth/third-party", &AuthController{}, "post:LoginThirdParty")
 *                    in fe/http/uic/uic_routes.go
 */
func (this *AuthController) LoginThirdParty() {
	s := g.Config().Api.Redirect
	s = base64.StdEncoding.EncodeToString([]byte(s))
	strEncoded := url.QueryEscape(s)
	loginUrl := g.Config().Api.Login + "/" + strEncoded
	this.ServeDataJson(loginUrl)
}

/**
 * @function name:   func getRequest(url string) map[string]interface{}
 * @description:     This function sends GET request to given URL.
 * @related issues:  OWL-206, OWL-159
 * @param:           url string
 * @return:          map[string]interface{}
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       func (this *AuthController) LoginWithToken()
 *                    in fe/http/uic/auth_controller.go
 */
func getRequest(url string) map[string]interface{} {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println("Error =", err.Error())
	}

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

	body, _ := ioutil.ReadAll(resp.Body)
	var nodes = make(map[string]interface{})
	if err := json.Unmarshal(body, &nodes); err != nil {
		log.Println("Error =", err.Error())
	}
	return nodes
}

/**
 * @function name:   func (this *AuthController) LoginWithToken()
 * @description:     This function logins user with third party token.
 * @related issues:  OWL-206
 * @param:           void
 * @return:          void
 * @author:          Don Hsieh
 * @since:           12/16/2015
 * @last modified:   12/17/2015
 * @called by:       beego.Router("/auth/login/:token", &AuthController{}, "get:LoginWithToken")
 *                    in fe/http/uic/uic_routes.go
 */
func (this *AuthController) LoginWithToken() {
	token := this.Ctx.Input.Param(":token")
	key := g.Config().Api.Key
	authUrl := g.Config().Api.Access + "/" + token + "/" + key

	nodes := getRequest(authUrl)
	if status, ok := nodes["status"]; ok {
		if int(status.(float64)) == 1 {
			data := nodes["data"].(map[string]interface {})
			access_key := data["access_key"].(string)
			username := data["username"].(string)
			email := data["email"].(string)
			log.Println("access_key =", access_key)

			urlRole := g.Config().Api.Role + "/" + access_key
			nodes := getRequest(urlRole)
			role := 3
			if int(nodes["status"].(float64)) == 1 {
				permission := nodes["data"]
				log.Println("permission =", permission)
				if permission == "admin" {
					role = 0
				} else if permission == "operator" {
					role = 1
				} else if permission == "observer" {
					role = 2
				} else if permission == "deny" {
					role = 3
				}
			}
			user := ReadUserByName(username)
			if user == nil {		// create third party user
				InsertRegisterUser(username, "")
				user = ReadUserByName(username)
			}
			user.Passwd = ""
			user.Email = email
			user.Role = role
			user.Update()
			appSig := this.GetString("sig", "")
			callback := this.GetString("callback", "")
			if appSig != "" && callback != "" {
				SaveSessionAttrs(user.Id, appSig, int(time.Now().Unix())+3600*24*30)
			} else {
				this.CreateSession(user.Id, 3600*24*30)
			}
			maxAge := 3600*24*30
			this.Ctx.SetCookie("token", token, maxAge, "/")
			this.Ctx.SetCookie("token", token, maxAge, "/", ".owlemon.com")
			this.Redirect("/me/info", 302)
		}
	}
	// not logged in. redirect to login page.
	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")
	this.renderLoginPage(appSig, callback)
}
<commit_msg>[OWL-186] set value of token cookie as access_key for logout API<commit_after>package uic

import (
	"encoding/base64"
	"encoding/json"
	"io/ioutil"
	"log"
	"github.com/Cepave/fe/g"
	"github.com/Cepave/fe/http/base"
	. "github.com/Cepave/fe/model/uic"
	"github.com/Cepave/fe/utils"
	"github.com/toolkits/str"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type AuthController struct {
	base.BaseController
}

func (this *AuthController) Logout() {
	u := this.Ctx.Input.GetData("CurrentUser").(*User)
	token := this.Ctx.GetCookie("token")
	if len(token) > 0 {
		url := g.Config().Api.Logout + "/" + token
		log.Println("logout url =", url)
		result := getRequest(url)
		log.Println("logout result =", result)
		this.Ctx.SetCookie("token", "", 0, "/")
		this.Ctx.SetCookie("token", "", 0, "/", ".owlemon.com")
	}
	RemoveSessionByUid(u.Id)
	this.Ctx.SetCookie("sig", "", 0, "/")
	this.Ctx.SetCookie("sig", "", 0, "/", ".owlemon.com")
	this.Redirect("/auth/login", 302)
}

func (this *AuthController) LoginGet() {
	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")

	cookieSig := this.Ctx.GetCookie("sig")
	if cookieSig == "" {
		this.renderLoginPage(appSig, callback)
		return
	}

	sessionObj := ReadSessionBySig(cookieSig)
	if sessionObj == nil {
		this.renderLoginPage(appSig, callback)
		return
	}

	if int64(sessionObj.Expired) < time.Now().Unix() {
		RemoveSessionByUid(sessionObj.Uid)
		this.renderLoginPage(appSig, callback)
		return
	}

	if appSig != "" && callback != "" {
		this.Redirect(callback, 302)
	} else {
		this.Redirect("/me/info", 302)
	}
}

func (this *AuthController) LoginPost() {
	name := this.GetString("name", "")
	password := this.GetString("password", "")

	if name == "" || password == "" {
		this.ServeErrJson("name or password is blank")
		return
	}

	var u *User

	ldapEnabled := this.MustGetBool("ldap", false)

	if ldapEnabled {
		sucess, err := utils.LdapBind(g.Config().Ldap.Addr, name, password)
		if err != nil {
			this.ServeErrJson(err.Error())
			return
		}

		if !sucess {
			this.ServeErrJson("name or password error")
			return
		}

		arr := strings.Split(name, "@")
		var userName, userEmail string
		if len(arr) == 2 {
			userName = arr[0]
			userEmail = name
		} else {
			userName = name
			userEmail = ""
		}

		u = ReadUserByName(userName)
		if u == nil {
			// 说明用户不存在
			u = &User{
				Name:   userName,
				Passwd: "",
				Email:  userEmail,
			}
			_, err = u.Save()
			if err != nil {
				this.ServeErrJson("insert user fail " + err.Error())
				return
			}
		}
	} else {
		u = ReadUserByName(name)
		if u == nil {
			this.ServeErrJson("no such user")
			return
		}

		if u.Passwd != str.Md5Encode(g.Config().Salt+password) {
			this.ServeErrJson("password error")
			return
		}
	}

	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")
	if appSig != "" && callback != "" {
		SaveSessionAttrs(u.Id, appSig, int(time.Now().Unix())+3600*24*30)
	} else {
		this.CreateSession(u.Id, 3600*24*30)
	}

	this.ServeDataJson(callback)
}

func (this *AuthController) renderLoginPage(sig, callback string) {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["LdapEnabled"] = g.Config().Ldap.Enabled
	this.Data["Sig"] = sig
	this.Data["Callback"] = callback
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/login.html"
}

func (this *AuthController) RegisterGet() {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/register.html"
}

func (this *AuthController) RegisterPost() {
	if !g.Config().CanRegister {
		this.ServeErrJson("registration system is not open")
		return
	}

	name := strings.TrimSpace(this.GetString("name", ""))
	password := strings.TrimSpace(this.GetString("password", ""))
	repeatPassword := strings.TrimSpace(this.GetString("repeat_password", ""))

	if password != repeatPassword {
		this.ServeErrJson("password not equal the repeart one")
		return
	}

	if !utils.IsUsernameValid(name) {
		this.ServeErrJson("name pattern is invalid")
		return
	}

	if ReadUserIdByName(name) > 0 {
		this.ServeErrJson("name is already existent")
		return
	}

	lastId, err := InsertRegisterUser(name, str.Md5Encode(g.Config().Salt+password))
	if err != nil {
		this.ServeErrJson("insert user fail " + err.Error())
		return
	}

	this.CreateSession(lastId, 3600*24*30)

	this.ServeOKJson()
}

func (this *AuthController) CreateSession(uid int64, maxAge int) int {
	sig := utils.GenerateUUID()
	expired := int(time.Now().Unix()) + maxAge
	SaveSessionAttrs(uid, sig, expired)
	this.Ctx.SetCookie("sig", sig, maxAge, "/")
	this.Ctx.SetCookie("sig", sig, maxAge, "/", ".owlemon.com")
	return expired
}

/**
 * @function name:   func (this *AuthController) LoginThirdParty()
 * @description:     This function returns third party login URL.
 * @related issues:  OWL-206
 * @param:           void
 * @return:          void
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       beego.Router("/auth/third-party", &AuthController{}, "post:LoginThirdParty")
 *                    in fe/http/uic/uic_routes.go
 */
func (this *AuthController) LoginThirdParty() {
	s := g.Config().Api.Redirect
	s = base64.StdEncoding.EncodeToString([]byte(s))
	strEncoded := url.QueryEscape(s)
	loginUrl := g.Config().Api.Login + "/" + strEncoded
	this.ServeDataJson(loginUrl)
}

/**
 * @function name:   func getRequest(url string) map[string]interface{}
 * @description:     This function sends GET request to given URL.
 * @related issues:  OWL-206, OWL-159
 * @param:           url string
 * @return:          map[string]interface{}
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       func (this *AuthController) LoginWithToken()
 *                    in fe/http/uic/auth_controller.go
 */
func getRequest(url string) map[string]interface{} {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println("Error =", err.Error())
	}

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

	body, _ := ioutil.ReadAll(resp.Body)
	var nodes = make(map[string]interface{})
	if err := json.Unmarshal(body, &nodes); err != nil {
		log.Println("Error =", err.Error())
	}
	return nodes
}

/**
 * @function name:   func (this *AuthController) LoginWithToken()
 * @description:     This function logins user with third party token.
 * @related issues:  OWL-206
 * @param:           void
 * @return:          void
 * @author:          Don Hsieh
 * @since:           12/16/2015
 * @last modified:   12/21/2015
 * @called by:       beego.Router("/auth/login/:token", &AuthController{}, "get:LoginWithToken")
 *                    in fe/http/uic/uic_routes.go
 */
func (this *AuthController) LoginWithToken() {
	token := this.Ctx.Input.Param(":token")
	key := g.Config().Api.Key
	authUrl := g.Config().Api.Access + "/" + token + "/" + key

	nodes := getRequest(authUrl)
	if status, ok := nodes["status"]; ok {
		if int(status.(float64)) == 1 {
			data := nodes["data"].(map[string]interface {})
			access_key := data["access_key"].(string)
			username := data["username"].(string)
			email := data["email"].(string)
			log.Println("access_key =", access_key)

			urlRole := g.Config().Api.Role + "/" + access_key
			nodes := getRequest(urlRole)
			role := 3
			if int(nodes["status"].(float64)) == 1 {
				permission := nodes["data"]
				log.Println("permission =", permission)
				if permission == "admin" {
					role = 0
				} else if permission == "operator" {
					role = 1
				} else if permission == "observer" {
					role = 2
				} else if permission == "deny" {
					role = 3
				}
				maxAge := 3600*24*30
				this.Ctx.SetCookie("token", access_key, maxAge, "/")
				this.Ctx.SetCookie("token", access_key, maxAge, "/", ".owlemon.com")
			}
			user := ReadUserByName(username)
			if user == nil {		// create third party user
				InsertRegisterUser(username, "")
				user = ReadUserByName(username)
			}
			user.Passwd = ""
			user.Email = email
			user.Role = role
			user.Update()
			appSig := this.GetString("sig", "")
			callback := this.GetString("callback", "")
			if appSig != "" && callback != "" {
				SaveSessionAttrs(user.Id, appSig, int(time.Now().Unix())+3600*24*30)
			} else {
				this.CreateSession(user.Id, 3600*24*30)
			}
			this.Redirect("/me/info", 302)
		}
	}
	// not logged in. redirect to login page.
	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")
	this.renderLoginPage(appSig, callback)
}
<|endoftext|>


<commit_before>package vrp

import (
	"fmt"

	"honnef.co/go/tools/ssa"
)

type ChannelInterval struct {
	Size IntInterval
}

func (c ChannelInterval) Union(other Range) Range {
	i, ok := other.(ChannelInterval)
	if !ok {
		i = ChannelInterval{EmptyIntInterval}
	}
	if c.Size.Empty() || !c.Size.IsKnown() {
		return i
	}
	if i.Size.Empty() || !i.Size.IsKnown() {
		return c
	}
	return ChannelInterval{
		Size: c.Size.Union(i.Size).(IntInterval),
	}
}

func (c ChannelInterval) String() string {
	return c.Size.String()
}

func (c ChannelInterval) IsKnown() bool {
	return c.Size.IsKnown()
}

type MakeChannelConstraint struct {
	aConstraint
	Buffer ssa.Value
}
type ChannelChangeTypeConstraint struct {
	aConstraint
	X ssa.Value
}

func NewMakeChannelConstraint(buffer, y ssa.Value) Constraint {
	return &MakeChannelConstraint{NewConstraint(y), buffer}
}
func NewChannelChangeTypeConstraint(x, y ssa.Value) Constraint {
	return &ChannelChangeTypeConstraint{NewConstraint(y), x}
}

func (c *MakeChannelConstraint) Operands() []ssa.Value       { return []ssa.Value{c.Buffer} }
func (c *ChannelChangeTypeConstraint) Operands() []ssa.Value { return []ssa.Value{c.X} }

func (c *MakeChannelConstraint) String() string {
	return fmt.Sprintf("%s = make(chan, %s)", c.Y().Name, c.Buffer.Name())
}
func (c *ChannelChangeTypeConstraint) String() string {
	return fmt.Sprintf("%s = changetype(%s)", c.Y().Name, c.X.Name())
}

func (c *MakeChannelConstraint) Eval(g *Graph) Range {
	i, ok := g.Range(c.Buffer).(IntInterval)
	if !ok {
		return ChannelInterval{NewIntInterval(NewZ(0), PInfinity)}
	}
	if i.Lower.Sign() == -1 {
		i.Lower = NewZ(0)
	}
	return ChannelInterval{i}
}
func (c *ChannelChangeTypeConstraint) Eval(g *Graph) Range { return g.Range(c.X) }
<commit_msg>staticcheck/vrp: fix String methods<commit_after>package vrp

import (
	"fmt"

	"honnef.co/go/tools/ssa"
)

type ChannelInterval struct {
	Size IntInterval
}

func (c ChannelInterval) Union(other Range) Range {
	i, ok := other.(ChannelInterval)
	if !ok {
		i = ChannelInterval{EmptyIntInterval}
	}
	if c.Size.Empty() || !c.Size.IsKnown() {
		return i
	}
	if i.Size.Empty() || !i.Size.IsKnown() {
		return c
	}
	return ChannelInterval{
		Size: c.Size.Union(i.Size).(IntInterval),
	}
}

func (c ChannelInterval) String() string {
	return c.Size.String()
}

func (c ChannelInterval) IsKnown() bool {
	return c.Size.IsKnown()
}

type MakeChannelConstraint struct {
	aConstraint
	Buffer ssa.Value
}
type ChannelChangeTypeConstraint struct {
	aConstraint
	X ssa.Value
}

func NewMakeChannelConstraint(buffer, y ssa.Value) Constraint {
	return &MakeChannelConstraint{NewConstraint(y), buffer}
}
func NewChannelChangeTypeConstraint(x, y ssa.Value) Constraint {
	return &ChannelChangeTypeConstraint{NewConstraint(y), x}
}

func (c *MakeChannelConstraint) Operands() []ssa.Value       { return []ssa.Value{c.Buffer} }
func (c *ChannelChangeTypeConstraint) Operands() []ssa.Value { return []ssa.Value{c.X} }

func (c *MakeChannelConstraint) String() string {
	return fmt.Sprintf("%s = make(chan, %s)", c.Y().Name(), c.Buffer.Name())
}
func (c *ChannelChangeTypeConstraint) String() string {
	return fmt.Sprintf("%s = changetype(%s)", c.Y().Name(), c.X.Name())
}

func (c *MakeChannelConstraint) Eval(g *Graph) Range {
	i, ok := g.Range(c.Buffer).(IntInterval)
	if !ok {
		return ChannelInterval{NewIntInterval(NewZ(0), PInfinity)}
	}
	if i.Lower.Sign() == -1 {
		i.Lower = NewZ(0)
	}
	return ChannelInterval{i}
}
func (c *ChannelChangeTypeConstraint) Eval(g *Graph) Range { return g.Range(c.X) }
<|endoftext|>


<commit_before>package contactcenteranalysis

import "google.golang.org/genproto/googleapis/cloud/language/v1"

type supportedLanguage struct {
	// The languaged as a [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
	// language tag for Speech-to-Text.
	// See [Language Support](https://cloud.google.com/speech-to-text/docs/languages).
	Code string `json:"code"`
	Name string `json:"name"`

	punctuation  bool
	languageCode string
}

var (
	languageSupportedFeatures map[string]*language.AnnotateTextRequest_Features = map[string]*language.AnnotateTextRequest_Features{
		"zh": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"zh-Hant": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"en": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   true,
			ClassifyText:             true,
		},
		"fr": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"de": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"it": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"ja": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   true,
			ClassifyText:             false,
		},
		"ko": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"es": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   true,
			ClassifyText:             false,
		},
	}

	supportedLanguages []*supportedLanguage = []*supportedLanguage{
		{
			Code:         "zh",
			Name:         "Chinese, Mandarin (Simplified, China)",
			punctuation:  true,
			languageCode: "zh",
		},
		{
			Code:         "zh-TW",
			Name:         "Chinese, Mandarin (Traditional, Taiwan)",
			punctuation:  true,
			languageCode: "zh-Hant",
		},
		{
			Code:         "en-AU",
			Name:         "English (Australia)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-IN",
			Name:         "English (India)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-SG",
			Name:         "English (Singapore)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-GB",
			Name:         "English (United Kingdom)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-US",
			Name:         "English (United States)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "fr-FR",
			Name:         "French (France)",
			punctuation:  true,
			languageCode: "fr",
		},
		{
			Code:         "de-DE",
			Name:         "German (Germany)",
			punctuation:  true,
			languageCode: "de",
		},
		{
			Code:         "it-IT",
			Name:         "Italian (Italy)",
			punctuation:  true,
			languageCode: "it",
		},
		{
			Code:         "ja-JP",
			Name:         "Japanese (Japan)",
			punctuation:  true,
			languageCode: "ja",
		},
		{
			Code:         "ko-KR",
			Name:         "Korean (South Korea)",
			punctuation:  true,
			languageCode: "ko",
		},
		{
			Code:         "es-US",
			Name:         "Spanish (United States)",
			punctuation:  true,
			languageCode: "es",
		},
	}
)
<commit_msg>Disable classifyText of English<commit_after>package contactcenteranalysis

import "google.golang.org/genproto/googleapis/cloud/language/v1"

type supportedLanguage struct {
	// The languaged as a [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
	// language tag for Speech-to-Text.
	// See [Language Support](https://cloud.google.com/speech-to-text/docs/languages).
	Code string `json:"code"`
	Name string `json:"name"`

	punctuation  bool
	languageCode string
}

var (
	languageSupportedFeatures map[string]*language.AnnotateTextRequest_Features = map[string]*language.AnnotateTextRequest_Features{
		"zh": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"zh-Hant": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"en": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   true,
			ClassifyText:             false,
			// ClassifyText:             true,
		},
		"fr": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"de": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"it": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"ja": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   true,
			ClassifyText:             false,
		},
		"ko": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   false,
			ClassifyText:             false,
		},
		"es": {
			ExtractSyntax:            true,
			ExtractEntities:          true,
			ExtractDocumentSentiment: true,
			ExtractEntitySentiment:   true,
			ClassifyText:             false,
		},
	}

	supportedLanguages []*supportedLanguage = []*supportedLanguage{
		{
			Code:         "zh",
			Name:         "Chinese, Mandarin (Simplified, China)",
			punctuation:  true,
			languageCode: "zh",
		},
		{
			Code:         "zh-TW",
			Name:         "Chinese, Mandarin (Traditional, Taiwan)",
			punctuation:  true,
			languageCode: "zh-Hant",
		},
		{
			Code:         "en-AU",
			Name:         "English (Australia)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-IN",
			Name:         "English (India)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-SG",
			Name:         "English (Singapore)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-GB",
			Name:         "English (United Kingdom)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "en-US",
			Name:         "English (United States)",
			punctuation:  true,
			languageCode: "en",
		},
		{
			Code:         "fr-FR",
			Name:         "French (France)",
			punctuation:  true,
			languageCode: "fr",
		},
		{
			Code:         "de-DE",
			Name:         "German (Germany)",
			punctuation:  true,
			languageCode: "de",
		},
		{
			Code:         "it-IT",
			Name:         "Italian (Italy)",
			punctuation:  true,
			languageCode: "it",
		},
		{
			Code:         "ja-JP",
			Name:         "Japanese (Japan)",
			punctuation:  true,
			languageCode: "ja",
		},
		{
			Code:         "ko-KR",
			Name:         "Korean (South Korea)",
			punctuation:  true,
			languageCode: "ko",
		},
		{
			Code:         "es-US",
			Name:         "Spanish (United States)",
			punctuation:  true,
			languageCode: "es",
		},
	}
)
<|endoftext|>


<commit_before>package scanner

import (
	"encoding/gob"
	"errors"
	"fmt"
	"github.com/Symantec/Dominator/lib/image"
	"github.com/Symantec/Dominator/objectserver"
	"log"
	"os"
	"path"
	"syscall"
	"time"
)

func loadImageDataBase(baseDir string, objSrv objectserver.ObjectServer,
	logger *log.Logger) (*ImageDataBase, error) {
	fi, err := os.Stat(baseDir)
	if err != nil {
		return nil, errors.New(
			fmt.Sprintf("Cannot stat: %s\t%s\n", baseDir, err))
	}
	if !fi.IsDir() {
		return nil, errors.New(fmt.Sprintf("%s is not a directory\n", baseDir))
	}
	imdb := new(ImageDataBase)
	imdb.baseDir = baseDir
	imdb.imageMap = make(map[string]*image.Image)
	imdb.addNotifiers = make(notifiers)
	imdb.deleteNotifiers = make(notifiers)
	imdb.objectServer = objSrv
	imdb.logger = logger
	startTime := time.Now()
	var rusageStart, rusageStop syscall.Rusage
	syscall.Getrusage(syscall.RUSAGE_SELF, &rusageStart)
	if err = imdb.scanDirectory(""); err != nil {
		return nil, err
	}
	if logger != nil {
		plural := ""
		if imdb.CountImages() != 1 {
			plural = "s"
		}
		syscall.Getrusage(syscall.RUSAGE_SELF, &rusageStop)
		userTime := time.Duration(rusageStop.Utime.Sec)*time.Second +
			time.Duration(rusageStop.Utime.Usec)*time.Microsecond -
			time.Duration(rusageStart.Utime.Sec)*time.Second -
			time.Duration(rusageStart.Utime.Usec)*time.Microsecond
		logger.Printf("Loaded %d image%s in %s (%s user CPUtime)\n",
			imdb.CountImages(), plural, time.Since(startTime), userTime)
	}
	return imdb, nil
}

func (imdb *ImageDataBase) scanDirectory(dirname string) error {
	file, err := os.Open(path.Join(imdb.baseDir, dirname))
	if err != nil {
		return err
	}
	names, err := file.Readdirnames(-1)
	file.Close()
	for _, name := range names {
		filename := path.Join(dirname, name)
		var stat syscall.Stat_t
		err := syscall.Lstat(path.Join(imdb.baseDir, filename), &stat)
		if err != nil {
			if err == syscall.ENOENT {
				continue
			}
			return err
		}
		if stat.Mode&syscall.S_IFMT == syscall.S_IFDIR {
			err = imdb.scanDirectory(filename)
		} else if stat.Mode&syscall.S_IFMT == syscall.S_IFREG {
			err = imdb.loadFile(filename)
		}
		if err != nil {
			if err == syscall.ENOENT {
				continue
			}
			return err
		}
	}
	return nil
}

func (imdb *ImageDataBase) loadFile(filename string) error {
	file, err := os.Open(path.Join(imdb.baseDir, filename))
	if err != nil {
		return err
	}
	defer file.Close()
	decoder := gob.NewDecoder(file)
	var image image.Image
	if err = decoder.Decode(&image); err != nil {
		return err
	}
	image.FileSystem.RebuildInodePointers()
	imdb.imageMap[filename] = &image
	return nil
}
<commit_msg>Load images concurrently at imageserver startup.<commit_after>package scanner

import (
	"encoding/gob"
	"errors"
	"fmt"
	"github.com/Symantec/Dominator/lib/image"
	"github.com/Symantec/Dominator/objectserver"
	"log"
	"os"
	"path"
	"runtime"
	"syscall"
	"time"
)

type concurrencyState struct {
	semaphore    chan struct{}
	errorChannel chan error
	pending      uint64
}

func newConcurrencyState() *concurrencyState {
	state := new(concurrencyState)
	state.semaphore = make(chan struct{}, runtime.NumCPU())
	state.errorChannel = make(chan error)
	return state
}

func (state *concurrencyState) goFunc(doFunc func(string) error,
	filename string) error {
	for {
		select {
		case err := <-state.errorChannel:
			state.pending--
			if err != nil {
				return err
			}
		case state.semaphore <- struct{}{}:
			state.pending++
			go func(filename string) {
				state.errorChannel <- doFunc(filename)
				<-state.semaphore
			}(filename)
			return nil
		}
	}
}

func (state *concurrencyState) close() error {
	close(state.semaphore)
	for ; state.pending > 0; state.pending-- {
		if err := <-state.errorChannel; err != nil {
			return err
		}
	}
	close(state.errorChannel)
	return nil
}

func loadImageDataBase(baseDir string, objSrv objectserver.ObjectServer,
	logger *log.Logger) (*ImageDataBase, error) {
	fi, err := os.Stat(baseDir)
	if err != nil {
		return nil, errors.New(
			fmt.Sprintf("Cannot stat: %s\t%s\n", baseDir, err))
	}
	if !fi.IsDir() {
		return nil, errors.New(fmt.Sprintf("%s is not a directory\n", baseDir))
	}
	imdb := new(ImageDataBase)
	imdb.baseDir = baseDir
	imdb.imageMap = make(map[string]*image.Image)
	imdb.addNotifiers = make(notifiers)
	imdb.deleteNotifiers = make(notifiers)
	imdb.objectServer = objSrv
	imdb.logger = logger
	state := newConcurrencyState()
	startTime := time.Now()
	var rusageStart, rusageStop syscall.Rusage
	syscall.Getrusage(syscall.RUSAGE_SELF, &rusageStart)
	if err := imdb.scanDirectory("", state); err != nil {
		return nil, err
	}
	if err := state.close(); err != nil {
		return nil, err
	}
	if logger != nil {
		plural := ""
		if imdb.CountImages() != 1 {
			plural = "s"
		}
		syscall.Getrusage(syscall.RUSAGE_SELF, &rusageStop)
		userTime := time.Duration(rusageStop.Utime.Sec)*time.Second +
			time.Duration(rusageStop.Utime.Usec)*time.Microsecond -
			time.Duration(rusageStart.Utime.Sec)*time.Second -
			time.Duration(rusageStart.Utime.Usec)*time.Microsecond
		logger.Printf("Loaded %d image%s in %s (%s user CPUtime)\n",
			imdb.CountImages(), plural, time.Since(startTime), userTime)
	}
	return imdb, nil
}

func (imdb *ImageDataBase) scanDirectory(dirname string,
	state *concurrencyState) error {
	file, err := os.Open(path.Join(imdb.baseDir, dirname))
	if err != nil {
		return err
	}
	names, err := file.Readdirnames(-1)
	file.Close()
	for _, name := range names {
		filename := path.Join(dirname, name)
		var stat syscall.Stat_t
		err := syscall.Lstat(path.Join(imdb.baseDir, filename), &stat)
		if err != nil {
			if err == syscall.ENOENT {
				continue
			}
			return err
		}
		if stat.Mode&syscall.S_IFMT == syscall.S_IFDIR {
			err = imdb.scanDirectory(filename, state)
		} else if stat.Mode&syscall.S_IFMT == syscall.S_IFREG {
			err = state.goFunc(imdb.loadFile, filename)
		}
		if err != nil {
			if err == syscall.ENOENT {
				continue
			}
			return err
		}
	}
	return nil
}

func (imdb *ImageDataBase) loadFile(filename string) error {
	file, err := os.Open(path.Join(imdb.baseDir, filename))
	if err != nil {
		return err
	}
	defer file.Close()
	decoder := gob.NewDecoder(file)
	var image image.Image
	if err = decoder.Decode(&image); err != nil {
		return err
	}
	image.FileSystem.RebuildInodePointers()
	imdb.Lock()
	defer imdb.Unlock()
	imdb.imageMap[filename] = &image
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Arista Networks, Inc.  All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package types

import (
	"encoding/json"
	"fmt"
)

// Key represents the Key in the updates and deletes of the Notification
// objects.  The only reason this exists is that Go won't let us define
// our own hash function for non-hashable types, and unfortunately we
// need to be able to index maps by map[string]interface{} objects.
type Key interface {
	Key() interface{}
	String() string
	Equal(other interface{}) bool

	// IsHashable is true if this key is hashable and can be accessed in O(1) in a Go map.
	// If false, then a O(N) lookup is required to find this key in a Go map.
	// The only kind of unhashable key currently supported is map[string]interface{}.
	IsHashable() bool

	// Helper methods to manipulate maps keyed by `Key'.

	// GetFromMap returns the value for the entry of this Key.
	GetFromMap(map[Key]interface{}) (interface{}, bool)
	// DeleteFromMap deletes the entry in the map for this Key.
	// This is a no-op if the key does not exist in the map.
	DeleteFromMap(map[Key]interface{})
	// SetToMap updates or inserts an entry in the map for this Key.
	SetToMap(m map[Key]interface{}, value interface{})
}

type keyImpl struct {
	key interface{}
}

// NewKey returns a Key object implementing the Key interface
// to wrapped the key passed in
func NewKey(intf interface{}) Key {
	switch t := intf.(type) {
	case map[string]interface{}:
		intf = &t
	case int8, int16, int32, int64,
		uint8, uint16, uint32, uint64,
		float32, float64, string, bool:
	default:
		panic(fmt.Sprintf("Invalid type for key: %T", intf))
	}
	return keyImpl{key: intf}
}

func (k keyImpl) Key() interface{} {
	if m, ok := k.key.(*map[string]interface{}); ok {
		return *m
	}
	return k.key
}

func (k keyImpl) String() string {
	str, err := StringifyInterface(k.key)
	if err != nil {
		panic("Unable to stringify Key: " + err.Error())
	}
	return str
}

func isHashableMap(m map[Key]interface{}) bool {
	for k := range m {
		return k.IsHashable()
	}
	return true
}

func (k keyImpl) IsHashable() bool {
	_, ok := k.key.(*map[string]interface{})
	return !ok
}

func (k keyImpl) GetFromMap(m map[Key]interface{}) (interface{}, bool) {
	if len(m) == 0 {
		return nil, false
	}
	if isHashableMap(m) {
		v, ok := m[k]
		return v, ok
	}
	for key, value := range m {
		if k.Equal(key) {
			return value, true
		}
	}
	return nil, false
}
func (k keyImpl) DeleteFromMap(m map[Key]interface{}) {
	if len(m) == 0 {
		return
	}
	if isHashableMap(m) {
		delete(m, k)
		return
	}
	for key := range m {
		if k.Equal(key) {
			delete(m, key)
			return
		}
	}
}

func (k keyImpl) SetToMap(m map[Key]interface{}, value interface{}) {
	if isHashableMap(m) {
		m[k] = value
		return
	}
	for key := range m {
		if k.Equal(key) {
			m[key] = value
			return
		}
	}
	m[k] = value
}

func (k keyImpl) GoString() string {
	return fmt.Sprintf("types.NewKey(%#v)", k.Key())
}

func (k keyImpl) MarshalJSON() ([]byte, error) {
	return json.Marshal(k.Key())
}

func (k keyImpl) Equal(other interface{}) bool {
	o, ok := other.(Key)
	if !ok {
		return false
	}
	if m, ok := k.key.(*map[string]interface{}); ok {
		m2, ok := o.Key().(map[string]interface{})
		return ok && keyEqual(*m, m2)
	}
	return keyEqual(k.key, o.Key())
}

func keyEqual(a, b interface{}) bool {
	if a, ok := a.(map[string]interface{}); ok {
		b, ok := b.(map[string]interface{})
		if !ok || len(a) != len(b) {
			return false
		}
		for k, av := range a {
			if bv, ok := (b)[k]; !ok || !keyEqual(av, bv) {
				return false
			}
		}
		return true
	}

	return a == b
}
<commit_msg>Remove some unnecessary parentheses that don't help readability.<commit_after>// Copyright (c) 2015 Arista Networks, Inc.  All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package types

import (
	"encoding/json"
	"fmt"
)

// Key represents the Key in the updates and deletes of the Notification
// objects.  The only reason this exists is that Go won't let us define
// our own hash function for non-hashable types, and unfortunately we
// need to be able to index maps by map[string]interface{} objects.
type Key interface {
	Key() interface{}
	String() string
	Equal(other interface{}) bool

	// IsHashable is true if this key is hashable and can be accessed in O(1) in a Go map.
	// If false, then a O(N) lookup is required to find this key in a Go map.
	// The only kind of unhashable key currently supported is map[string]interface{}.
	IsHashable() bool

	// Helper methods to manipulate maps keyed by `Key'.

	// GetFromMap returns the value for the entry of this Key.
	GetFromMap(map[Key]interface{}) (interface{}, bool)
	// DeleteFromMap deletes the entry in the map for this Key.
	// This is a no-op if the key does not exist in the map.
	DeleteFromMap(map[Key]interface{})
	// SetToMap updates or inserts an entry in the map for this Key.
	SetToMap(m map[Key]interface{}, value interface{})
}

type keyImpl struct {
	key interface{}
}

// NewKey returns a Key object implementing the Key interface
// to wrapped the key passed in
func NewKey(intf interface{}) Key {
	switch t := intf.(type) {
	case map[string]interface{}:
		intf = &t
	case int8, int16, int32, int64,
		uint8, uint16, uint32, uint64,
		float32, float64, string, bool:
	default:
		panic(fmt.Sprintf("Invalid type for key: %T", intf))
	}
	return keyImpl{key: intf}
}

func (k keyImpl) Key() interface{} {
	if m, ok := k.key.(*map[string]interface{}); ok {
		return *m
	}
	return k.key
}

func (k keyImpl) String() string {
	str, err := StringifyInterface(k.key)
	if err != nil {
		panic("Unable to stringify Key: " + err.Error())
	}
	return str
}

func isHashableMap(m map[Key]interface{}) bool {
	for k := range m {
		return k.IsHashable()
	}
	return true
}

func (k keyImpl) IsHashable() bool {
	_, ok := k.key.(*map[string]interface{})
	return !ok
}

func (k keyImpl) GetFromMap(m map[Key]interface{}) (interface{}, bool) {
	if len(m) == 0 {
		return nil, false
	}
	if isHashableMap(m) {
		v, ok := m[k]
		return v, ok
	}
	for key, value := range m {
		if k.Equal(key) {
			return value, true
		}
	}
	return nil, false
}
func (k keyImpl) DeleteFromMap(m map[Key]interface{}) {
	if len(m) == 0 {
		return
	}
	if isHashableMap(m) {
		delete(m, k)
		return
	}
	for key := range m {
		if k.Equal(key) {
			delete(m, key)
			return
		}
	}
}

func (k keyImpl) SetToMap(m map[Key]interface{}, value interface{}) {
	if isHashableMap(m) {
		m[k] = value
		return
	}
	for key := range m {
		if k.Equal(key) {
			m[key] = value
			return
		}
	}
	m[k] = value
}

func (k keyImpl) GoString() string {
	return fmt.Sprintf("types.NewKey(%#v)", k.Key())
}

func (k keyImpl) MarshalJSON() ([]byte, error) {
	return json.Marshal(k.Key())
}

func (k keyImpl) Equal(other interface{}) bool {
	o, ok := other.(Key)
	if !ok {
		return false
	}
	if m, ok := k.key.(*map[string]interface{}); ok {
		m2, ok := o.Key().(map[string]interface{})
		return ok && keyEqual(*m, m2)
	}
	return keyEqual(k.key, o.Key())
}

func keyEqual(a, b interface{}) bool {
	if a, ok := a.(map[string]interface{}); ok {
		b, ok := b.(map[string]interface{})
		if !ok || len(a) != len(b) {
			return false
		}
		for k, av := range a {
			if bv, ok := b[k]; !ok || !keyEqual(av, bv) {
				return false
			}
		}
		return true
	}

	return a == b
}
<|endoftext|>


<commit_before>package main

import "gopkg.in/h2non/bimg.v0"

type Options struct {
	Width, Height int
	Force         bool
	Operation     string
}

func Resize(image []byte, opts Options) (image []byte, err error) {
	defer func() {
		if r := recover(); r != nil {
			switch value := r.(type) {
			case error:
				err = value
			case string:
				err = errors.New(value)
			default:
				err = errors.New("libvips internal error")
			}
			image = []byte{}
		}
	}()

	params := bimg.Options{
		Enlarge:      true,
		NoAutoRotate: true,
		Width:        opts.Width,
		Height:       opts.Height,
		Force:        opts.Force,
		Crop:         opts.Operation == "crop" || opts.Operation == "resize",
	}

	return bimg.Resize(image, params)
}

func GetImageMimeType(code bimg.ImageType) string {
	if code == bimg.PNG {
		return "image/png"
	}
	if code == bimg.WEBP {
		return "image/webp"
	}
	return "image/jpeg"
}
<commit_msg>fix(resize)<commit_after>package main

import (
	"errors"
	"gopkg.in/h2non/bimg.v0"
)

type Options struct {
	Width, Height int
	Force         bool
	Operation     string
}

func Resize(image []byte, opts Options) (buf []byte, err error) {
	defer func() {
		if r := recover(); r != nil {
			switch value := r.(type) {
			case error:
				err = value
			case string:
				err = errors.New(value)
			default:
				err = errors.New("libvips internal error")
			}
			buf = []byte{}
		}
	}()

	params := bimg.Options{
		Enlarge:      true,
		NoAutoRotate: true,
		Width:        opts.Width,
		Height:       opts.Height,
		Force:        opts.Force,
		Crop:         opts.Operation == "crop" || opts.Operation == "resize",
	}

	return bimg.Resize(image, params)
}

func GetImageMimeType(code bimg.ImageType) string {
	if code == bimg.PNG {
		return "image/png"
	}
	if code == bimg.WEBP {
		return "image/webp"
	}
	return "image/jpeg"
}
<|endoftext|>


<commit_before>package sqlgen

import (
	"context"
	"testing"
	"time"

	"github.com/kylelemons/godebug/pretty"
	"github.com/samsarahq/thunder/internal/testfixtures"
)

func setup() (*testfixtures.TestDatabase, *DB, error) {
	testDb, err := testfixtures.NewTestDatabase()
	if err != nil {
		return nil, nil, err
	}

	if _, err = testDb.Exec(`
		CREATE TABLE users (
			id   BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
			name VARCHAR(255),
			uuid VARCHAR(255),
			mood VARCHAR(255)
		)
	`); err != nil {
		return nil, nil, err
	}
	schema := NewSchema()
	schema.MustRegisterType("users", AutoIncrement, User{})

	return testDb, NewDB(testDb.DB, schema), nil
}

type User struct {
	Id   int64 `sql:",primary"`
	Name string
	Uuid testfixtures.CustomType
	Mood *testfixtures.CustomType
}

func TestContextDeadlineEnforced(t *testing.T) {
	tdb, db, err := setup()
	if err != nil {
		t.Fatal(err)
	}
	defer tdb.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
	defer cancel()
	if _, err = db.QueryExecer(ctx).ExecContext(ctx, "DO SLEEP(1)"); err == nil || err != context.DeadlineExceeded {
		t.Errorf("Expected context.DeadlineExceeded, got: %s", err)
	}
}

func TestIntegrationBasic(t *testing.T) {
	tdb, db, err := setup()
	if err != nil {
		t.Fatal(err)
	}
	defer tdb.Close()

	mood := testfixtures.CustomType{'f', 'o', 'o', 'o', 'o', 'o', 'o'}

	if _, err := db.InsertRow(context.Background(), &User{Name: "Bob", Uuid: testfixtures.CustomType{'1', '1', '2', '3', '8', '4', '9', '1', '2', '9', '3'}, Mood: &mood}); err != nil {
		t.Error(err)
	}

	var users []*User
	if err := db.Query(context.Background(), &users, nil, nil); err != nil {
		t.Error(err)
	}

	if diff := pretty.Compare(users, []*User{
		{
			Id:   1,
			Name: "Bob",
			Uuid: testfixtures.CustomType{'1', '1', '2', '3', '8', '4', '9', '1', '2', '9', '3'},
			Mood: &mood,
		},
	}); diff != "" {
		t.Errorf("diff: %s", diff)
	}
}

// TestContextCancelBeforeRowsScan demonstrates we don't
// always get context.Canceled back from sql library. This
// affects our error handling and we need to be aware of it.
func TestContextCancelBeforeRowsScan(t *testing.T) {
	testDb, err := testfixtures.NewTestDatabase()
	if err != nil {
		t.Fatal(err)
	}
	defer testDb.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	rows, err := testDb.QueryContext(ctx, `select "foo"`)
	if err != nil {
		t.Fatal(err)
	}
	defer rows.Close()

	// When we cancel the context after rows.Next() returns true,
	// database/sql.(*Rows).initContextClose monitors the context
	// and closes rows asynchronously, and subsequent rows.Scan()
	// returns errors.New("sql: Rows are closed") instead of
	// context.Canceled.
	for rows.Next() {
		cancel()
		time.Sleep(1000 * time.Millisecond)

		var foo string
		err := rows.Scan(&foo)

		// err is not context.Canceled.
		if err == nil || err.Error() != "sql: Rows are closed" {
			t.Fatalf("expecting 'sql: Rows are closed' from rows.Scan(), got %v", err)
		}
	}
	if err := rows.Err(); err != context.Canceled {
		t.Fatalf("expecting context.Canceled from rows.Err(), got %v", err)
	}
}
<commit_msg>go sqlgen: add benchmarks<commit_after>package sqlgen

import (
	"context"
	"testing"
	"time"

	"github.com/kylelemons/godebug/pretty"
	"github.com/samsarahq/thunder/internal/testfixtures"
)

func setup() (*testfixtures.TestDatabase, *DB, error) {
	testDb, err := testfixtures.NewTestDatabase()
	if err != nil {
		return nil, nil, err
	}

	if _, err = testDb.Exec(`
		CREATE TABLE users (
			id   BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
			name VARCHAR(255),
			uuid VARCHAR(255),
			mood VARCHAR(255)
		)
	`); err != nil {
		return nil, nil, err
	}
	schema := NewSchema()
	schema.MustRegisterType("users", AutoIncrement, User{})

	return testDb, NewDB(testDb.DB, schema), nil
}

type User struct {
	Id   int64 `sql:",primary"`
	Name string
	Uuid testfixtures.CustomType
	Mood *testfixtures.CustomType
}

func TestContextDeadlineEnforced(t *testing.T) {
	tdb, db, err := setup()
	if err != nil {
		t.Fatal(err)
	}
	defer tdb.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
	defer cancel()
	if _, err = db.QueryExecer(ctx).ExecContext(ctx, "DO SLEEP(1)"); err == nil || err != context.DeadlineExceeded {
		t.Errorf("Expected context.DeadlineExceeded, got: %s", err)
	}
}

func TestIntegrationBasic(t *testing.T) {
	tdb, db, err := setup()
	if err != nil {
		t.Fatal(err)
	}
	defer tdb.Close()

	mood := testfixtures.CustomType{'f', 'o', 'o', 'o', 'o', 'o', 'o'}

	if _, err := db.InsertRow(context.Background(), &User{Name: "Bob", Uuid: testfixtures.CustomType{'1', '1', '2', '3', '8', '4', '9', '1', '2', '9', '3'}, Mood: &mood}); err != nil {
		t.Error(err)
	}

	var users []*User
	if err := db.Query(context.Background(), &users, nil, nil); err != nil {
		t.Error(err)
	}

	if diff := pretty.Compare(users, []*User{
		{
			Id:   1,
			Name: "Bob",
			Uuid: testfixtures.CustomType{'1', '1', '2', '3', '8', '4', '9', '1', '2', '9', '3'},
			Mood: &mood,
		},
	}); diff != "" {
		t.Errorf("diff: %s", diff)
	}
}

// TestContextCancelBeforeRowsScan demonstrates we don't
// always get context.Canceled back from sql library. This
// affects our error handling and we need to be aware of it.
func TestContextCancelBeforeRowsScan(t *testing.T) {
	testDb, err := testfixtures.NewTestDatabase()
	if err != nil {
		t.Fatal(err)
	}
	defer testDb.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	rows, err := testDb.QueryContext(ctx, `select "foo"`)
	if err != nil {
		t.Fatal(err)
	}
	defer rows.Close()

	// When we cancel the context after rows.Next() returns true,
	// database/sql.(*Rows).initContextClose monitors the context
	// and closes rows asynchronously, and subsequent rows.Scan()
	// returns errors.New("sql: Rows are closed") instead of
	// context.Canceled.
	for rows.Next() {
		cancel()
		time.Sleep(1000 * time.Millisecond)

		var foo string
		err := rows.Scan(&foo)

		// err is not context.Canceled.
		if err == nil || err.Error() != "sql: Rows are closed" {
			t.Fatalf("expecting 'sql: Rows are closed' from rows.Scan(), got %v", err)
		}
	}
	if err := rows.Err(); err != context.Canceled {
		t.Fatalf("expecting context.Canceled from rows.Err(), got %v", err)
	}
}

func Benchmark(b *testing.B) {
	tdb, db, err := setup()
	if err != nil {
		b.Fatal(err)
	}
	defer tdb.Close()

	ctx := context.Background()

	mood := testfixtures.CustomType{'f', 'o', 'o', 'o', 'o', 'o', 'o'}
	user := &User{
		Id:   1,
		Name: "Bob",
		Uuid: testfixtures.CustomType{'1', '1', '2', '3', '8', '4', '9', '1', '2', '9', '3'},
		Mood: &mood,
	}

	if _, err := db.InsertRow(ctx, user); err != nil {
		b.Fatal(err)
	}

	benchmarks := []struct {
		name string
		fn   func() error
	}{
		{"Read", func() error {
			user := &User{}
			return db.QueryRow(ctx, &user, nil, nil)
		}},
		{"Create", func() error {
			_, err := db.InsertRow(ctx, user)
			return err
		}},
		{"Update", func() error { return db.UpdateRow(ctx, user) }},
		{"Delete", func() error { return db.DeleteRow(ctx, user) }},
	}

	for _, bm := range benchmarks {
		b.Run(bm.name, func(b *testing.B) {
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				if err := bm.fn(); err != nil {
					b.Error(err)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>package wiki

import (
	"time"

	"github.com/cooper/quiki/wikifier"
)

// CategoryType describes the type of a Category.
type CategoryType string

var (
	// CategoryTypeImage is a type of category that tracks which pages use an image.
	CategoryTypeImage CategoryType = "image"

	// CategoryTypeModel is a type of category that tracks which pages use a model.
	CategoryTypeModel = "model"

	// CategoryTypePage is a type of category that tracks which pages reference another page.
	CategoryTypePage = "page"
)

// A Category is a collection of pages pertaining to a topic.
//
// A page can belong to many categories. Category memberships and metadta
// are stored in JSON manifests.
//
type Category struct {

	// category filename, including the .cat extension
	File string

	// category name without extension
	Name string

	// human-readable category title
	Title string

	// time when the category was created
	Created time.Time

	// time when the category was last modified.
	// this is updated when pages are added and deleted
	Modified time.Time

	// pages in the category. keys are filenames
	Pages map[string]CategoryEntry

	// when true, the category is preserved even when no pages remain
	Preserve bool

	// EXTRAS

	// if applicable, this is the type of pseudocategory.
	// for normal categories, this is empty
	Type CategoryType

	// for CategoryTypePage, this is the info for the tracked page
	PageInfo wikifier.PageInfo
}

// A CategoryEntry describes a page that belongs to a category.
type CategoryEntry struct {

	// time at which the page metadata in this category file was last updated.
	// this is compared against page file modification time
	Asof time.Time

	// embedded page info
	// note this info is accurate only as of the Asof time
	wikifier.PageInfo

	// EXTRAS

	// for CategoryTypeImage, an array of image dimensions used on this page.
	// dimensions are guaranteed to be positive integers. the number of elements will
	// always be even, since each occurence of the image produces two (width and then height)
	Dimensions [][]int

	// for CategoryTypePage, an array of line numbers on which the tracked page is
	// referenced on the page described by this entry
	Lines []int
}
<commit_msg>json tags<commit_after>package wiki

import (
	"time"

	"github.com/cooper/quiki/wikifier"
)

// CategoryType describes the type of a Category.
type CategoryType string

var (
	// CategoryTypeImage is a type of category that tracks which pages use an image.
	CategoryTypeImage CategoryType = "image"

	// CategoryTypeModel is a type of category that tracks which pages use a model.
	CategoryTypeModel = "model"

	// CategoryTypePage is a type of category that tracks which pages reference another page.
	CategoryTypePage = "page"
)

// A Category is a collection of pages pertaining to a topic.
//
// A page can belong to many categories. Category memberships and metadta
// are stored in JSON manifests.
//
type Category struct {

	// category filename, including the .cat extension
	File string `json:"file,omitempty"`

	// category name without extension
	Name string `json:"name,omitempty"`

	// human-readable category title
	Title string `json:"title,omitempty"`

	// time when the category was created
	Created time.Time `json:"created,omitempty"`

	// time when the category was last modified.
	// this is updated when pages are added and deleted
	Modified time.Time `json:"modified,omitempty"`

	// pages in the category. keys are filenames
	Pages map[string]CategoryEntry `json:"pages,omitempty"`

	// when true, the category is preserved even when no pages remain
	Preserve bool `json:"preserve,omitempty"`

	// EXTRAS

	// if applicable, this is the type of pseudocategory.
	// for normal categories, this is empty
	Type CategoryType `json:"type,omitempty"`

	// for CategoryTypePage, this is the info for the tracked page
	PageInfo wikifier.PageInfo `json:"page_info,omitempty"`
}

// A CategoryEntry describes a page that belongs to a category.
type CategoryEntry struct {

	// time at which the page metadata in this category file was last updated.
	// this is compared against page file modification time
	Asof time.Time `json:"asof,omitempty"`

	// embedded page info
	// note this info is accurate only as of the Asof time
	wikifier.PageInfo

	// EXTRAS

	// for CategoryTypeImage, an array of image dimensions used on this page.
	// dimensions are guaranteed to be positive integers. the number of elements will
	// always be even, since each occurence of the image produces two (width and then height)
	Dimensions [][]int `json:"dimensions,omitempty"`

	// for CategoryTypePage, an array of line numbers on which the tracked page is
	// referenced on the page described by this entry
	Lines []int `json:"lines,omitempty"`
}
<|endoftext|>


<commit_before>package rnglib

import "os"
import "strings"

// Version number tracked in ../CHANGES
func Version() (string, string) {
	return "0.2.1", "2013-07-05"
}

// a crude attempt at properties
var _FILE_NAME_STARTERS = strings.Split(
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", "")

func FILE_NAME_STARTERS() []string {
	return _FILE_NAME_STARTERS
}

var _FILE_NAME_CHARS = strings.Split(
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.", "")

func FILE_NAME_CHARS() []string {
	return _FILE_NAME_CHARS
}

/* XXX this should be in another package */
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
<commit_msg>stepped version number<commit_after>package rnglib

import "os"
import "strings"

// Version number tracked in ../CHANGES
func Version() (string, string) {
	return "0.3.0", "2013-08-07"
}

// a crude attempt at properties
var _FILE_NAME_STARTERS = strings.Split(
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", "")

func FILE_NAME_STARTERS() []string {
	return _FILE_NAME_STARTERS
}

var _FILE_NAME_CHARS = strings.Split(
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.", "")

func FILE_NAME_CHARS() []string {
	return _FILE_NAME_CHARS
}

/* XXX this should be in another package */
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
<|endoftext|>


<commit_before>// +build windows

// Package winlog provides convenience functions for using the Windows Event Log API.
package winlog

import (
	"fmt"
	"regexp"
	"syscall"
	"unsafe"

	log "github.com/golang/glog"
	"golang.org/x/sys/windows"
	"github.com/google/winops/winlog/wevtapi"
)

// Windows function parameters.
const (
	localMachine = 0 // Identifies the local machine for Windows API functions.
	mustBeZero   = 0 // For reserved Windows API function parameters.
)

// SubscribeConfig describes parameters for initializing a Windows Event Log subscription.
type SubscribeConfig struct {
	Session     windows.Handle
	SignalEvent windows.Handle
	ChannelPath *uint16
	Query       *uint16
	Bookmark    windows.Handle
	Context     uintptr
	Callback    uintptr
	Flags       uint32
}

// Close closes a Windows event log handle.
func Close(h windows.Handle) error {
	return wevtapi.EvtClose(h)
}

// DefaultSubscribeConfig creates a default subscriber configuration to be used
// to initialize a pull subscription for the classic Windows Event Log channels.
func DefaultSubscribeConfig() (*SubscribeConfig, error) {
	var config SubscribeConfig
	var err error

	// Create a subscription signaler.
	config.SignalEvent, err = windows.CreateEvent(
		nil, // Default security descriptor.
		1,   // Manual reset.
		1,   // Initial state is signaled.
		nil) // Optional name.
	if err != nil {
		return &config, fmt.Errorf("windows.CreateEvent failed: %v", err)
	}

	// Build a structured XML query retrieving all the events from the classic
	// Windows Event Log channels and start the subscription from the oldest record.
	config.Flags = wevtapi.EvtSubscribeStartAtOldestRecord
	xpaths := map[string]string{"Application": "*", "Security": "*", "System": "*"}
	xmlQuery, err := BuildStructuredXMLQuery(xpaths)
	if err != nil {
		return nil, fmt.Errorf("BuildStructuredXMLQuery failed: %v", err)
	}
	config.Query, err = syscall.UTF16PtrFromString(string(xmlQuery))
	if err != nil {
		return &config, fmt.Errorf("syscall.UTF16PtrFromString failed: %v", err)
	}

	return &config, nil
}

// GetRenderedEvents iterates over a subscription or query result set up to a configurable
// maximum and returns the rendered events as a slice of UTF8 formatted XML strings.
// publisherCache is a cache of Handles for publisher metadata to avoid
// expensive Windows API calls. Pass in an empty map on the first call. Once
// you've finished using GetRenderedEvents, pass all the contained values to Close.
func GetRenderedEvents(config *SubscribeConfig, publisherCache map[string]windows.Handle, resultSet windows.Handle, maxEvents int, locale uint32) ([]string, error) {
	var events = make([]windows.Handle, maxEvents)
	var returned uint32

	// Get handles to events from the result set.
	err := wevtapi.EvtNext(
		resultSet,           // Handle to query or subscription result set.
		uint32(len(events)), // The number of events to attempt to retrieve.
		&events[0],          // Pointer to the array of event handles.
		2000,                // Timeout in milliseconds to wait.
		0,                   // Reserved. Must be zero.
		&returned)           // The number of handles in the array that are set by the API.
	if err == windows.ERROR_NO_MORE_ITEMS {
		return nil, err
	} else if err != nil {
		return nil, fmt.Errorf("wevtapi.EvtNext failed: %v", err)
	}

	// Event handles must be closed after they are returned by EvtNext whether or not we use them.
	defer func() {
		for _, event := range events[:returned] {
			Close(event)
		}
	}()

	// Render events.
	var renderedEvents []string
	for _, event := range events[:returned] {
		// Render the basic XML representation of the event.
		fragment, err := RenderFragment(event, wevtapi.EvtRenderEventXml)
		if err != nil {
			log.Errorf("Failed to render event with EvtRenderEventXml, skipping: %v", err)
			continue
		}

		// Attempt to render the full event using the basic event.
		renderedEvent, err := RenderFormattedMessageXML(event, fragment, locale, publisherCache)
		if err != nil {
			log.Errorf("Failed to fully render event, returning fragment: %v\n%v", err, fragment)
			renderedEvent = fragment
		}
		renderedEvents = append(renderedEvents, renderedEvent)
	}

	// If a bookmark is used in the configuration, update it.
	if config.Bookmark != 0 {
		err = wevtapi.EvtUpdateBookmark(config.Bookmark, events[returned-1])
		if err != nil {
			return nil, fmt.Errorf("wevtapi.EvtUpdateBookmark failed: %v", err)
		}
	}

	return renderedEvents, err
}

// RenderFragment renders a Windows Event Log fragment according to the specified flag.
// Supports rendering events and bookmarks as UTF8 formatted XML strings.
func RenderFragment(fragment windows.Handle, flag uint32) (string, error) {
	var bufferUsed uint32
	var propertyCount uint32

	// Call EvtRender with a null buffer to get the required buffer size.
	err := wevtapi.EvtRender(
		0,
		fragment,
		flag,
		0,
		nil,
		&bufferUsed,
		&propertyCount)
	if err != syscall.ERROR_INSUFFICIENT_BUFFER {
		return "", fmt.Errorf("wevtapi.EvtRender failed: %v", err)
	}

	// Create a buffer based on the buffer size required.
	buf := make([]uint16, bufferUsed/2)

	// Render the fragment according to the flag.
	err = wevtapi.EvtRender(
		0,
		fragment,
		flag,
		bufferUsed,
		unsafe.Pointer(&buf[0]),
		&bufferUsed,
		&propertyCount)
	if err != nil {
		return "", fmt.Errorf("wevtapi.EvtRender failed: %v", err)
	}

	return syscall.UTF16ToString(buf), nil
}

// RenderFormattedMessageXML renders a Windows Event Log event as a UTF8 formatted XML string.
// This includes the RenderingInfo node parsed by leveraging the event publisher and desired
// locale (LCID). Returns the original raw XML if a publisher for the event is unavailable.
func RenderFormattedMessageXML(event windows.Handle, renderedEvent string, locale uint32, cache map[string]windows.Handle) (string, error) {
	// Find the event publisher using the raw event XML.
	re := regexp.MustCompile(`Provider Name='(.*?)\'`)
	publisherMatch := re.FindStringSubmatch(renderedEvent)
	if len(publisherMatch) < 2 {
		return "", fmt.Errorf("RenderFormattedMessageXML: no publisher name found in event")
	}
	publisherName := publisherMatch[1]

	// Lookup publisher metadata.
	var pubHandle windows.Handle
	if val, ok := cache[publisherName]; ok {
		pubHandle = val
	} else {
		var err error
		pubHandle, err = OpenPublisherMetadata(localMachine, publisherName, locale)
		// If there is no publisher metadata available return the original event.
		if err == syscall.ERROR_FILE_NOT_FOUND {
			return renderedEvent, nil
		} else if err != nil {
			return "", fmt.Errorf("OpenPublisherMetadata failed: %v", err)
		}
		cache[publisherName] = pubHandle
	}

	// Call EvtFormatMessage with a null buffer to get the required buffer size.
	var bufferUsed uint32
	err := wevtapi.EvtFormatMessage(
		pubHandle,                   // Handle to provider metadata.
		event,                       // Handle to an event.
		0,                           // Resource identifier of the message string. Null if flag isn't EvtFormatMessageId.
		0,                           // Number of values in the values parameter.
		0,                           // An array of insertion values to be used when formatting the event string. Typically set to null.
		wevtapi.EvtFormatMessageXml, // Format message as an XML string.
		0,                           // Size of buffer.
		nil,                         // Null buffer.
		&bufferUsed)                 // Get the required buffer size.
	if err != syscall.ERROR_INSUFFICIENT_BUFFER {
		return "", fmt.Errorf("wevtapi.EvtFormatMessage failed to get buffer size: %v", err)
	}

	buf := make([]uint16, bufferUsed/2)

	// Render the event as a formatted XML string with RenderingInfo node.
	err = wevtapi.EvtFormatMessage(pubHandle, event, 0, 0, 0, wevtapi.EvtFormatMessageXml,
		bufferUsed, (*byte)(unsafe.Pointer(&buf[0])), &bufferUsed)
	if err != nil {
		return "", fmt.Errorf("wevtapi.EvtFormatMessage failed to render events as formatted XML: %v", err)
	}

	return syscall.UTF16ToString(buf), nil
}

// Subscribe initializes a subscription and returns a handle to the subscription.
// Close must be called on the returned handle when finished.
func Subscribe(config *SubscribeConfig) (windows.Handle, error) {
	// Initialize the subscription.
	subscription, err := wevtapi.EvtSubscribe(
		config.Session,
		config.SignalEvent,
		config.ChannelPath,
		config.Query,
		config.Bookmark,
		config.Context,
		config.Callback,
		config.Flags)
	if err != nil {
		return 0, fmt.Errorf("wevtapi.EvtSubscribe failed: %v", err)
	}

	return subscription, nil
}
<commit_msg>Cache ERROR_FILE_NOT_FOUND result from OpenPublisherMetadata<commit_after>// +build windows

// Package winlog provides convenience functions for using the Windows Event Log API.
package winlog

import (
	"fmt"
	"regexp"
	"syscall"
	"unsafe"

	log "github.com/golang/glog"
	"golang.org/x/sys/windows"
	"github.com/google/winops/winlog/wevtapi"
)

// Windows function parameters.
const (
	localMachine = 0 // Identifies the local machine for Windows API functions.
	mustBeZero   = 0 // For reserved Windows API function parameters.
)

// SubscribeConfig describes parameters for initializing a Windows Event Log subscription.
type SubscribeConfig struct {
	Session     windows.Handle
	SignalEvent windows.Handle
	ChannelPath *uint16
	Query       *uint16
	Bookmark    windows.Handle
	Context     uintptr
	Callback    uintptr
	Flags       uint32
}

// Close closes a Windows event log handle.
func Close(h windows.Handle) error {
	if h == windows.InvalidHandle {
		// InvalidHandle is used to cache the "File not found" result
		// from OpenPublisherMetadata.
		return nil
	}

	return wevtapi.EvtClose(h)
}

// DefaultSubscribeConfig creates a default subscriber configuration to be used
// to initialize a pull subscription for the classic Windows Event Log channels.
func DefaultSubscribeConfig() (*SubscribeConfig, error) {
	var config SubscribeConfig
	var err error

	// Create a subscription signaler.
	config.SignalEvent, err = windows.CreateEvent(
		nil, // Default security descriptor.
		1,   // Manual reset.
		1,   // Initial state is signaled.
		nil) // Optional name.
	if err != nil {
		return &config, fmt.Errorf("windows.CreateEvent failed: %v", err)
	}

	// Build a structured XML query retrieving all the events from the classic
	// Windows Event Log channels and start the subscription from the oldest record.
	config.Flags = wevtapi.EvtSubscribeStartAtOldestRecord
	xpaths := map[string]string{"Application": "*", "Security": "*", "System": "*"}
	xmlQuery, err := BuildStructuredXMLQuery(xpaths)
	if err != nil {
		return nil, fmt.Errorf("BuildStructuredXMLQuery failed: %v", err)
	}
	config.Query, err = syscall.UTF16PtrFromString(string(xmlQuery))
	if err != nil {
		return &config, fmt.Errorf("syscall.UTF16PtrFromString failed: %v", err)
	}

	return &config, nil
}

// GetRenderedEvents iterates over a subscription or query result set up to a configurable
// maximum and returns the rendered events as a slice of UTF8 formatted XML strings.
// publisherCache is a cache of Handles for publisher metadata to avoid
// expensive Windows API calls. Pass in an empty map on the first call. Once
// you've finished using GetRenderedEvents, pass all the contained values to Close.
func GetRenderedEvents(config *SubscribeConfig, publisherCache map[string]windows.Handle, resultSet windows.Handle, maxEvents int, locale uint32) ([]string, error) {
	var events = make([]windows.Handle, maxEvents)
	var returned uint32

	// Get handles to events from the result set.
	err := wevtapi.EvtNext(
		resultSet,           // Handle to query or subscription result set.
		uint32(len(events)), // The number of events to attempt to retrieve.
		&events[0],          // Pointer to the array of event handles.
		2000,                // Timeout in milliseconds to wait.
		0,                   // Reserved. Must be zero.
		&returned)           // The number of handles in the array that are set by the API.
	if err == windows.ERROR_NO_MORE_ITEMS {
		return nil, err
	} else if err != nil {
		return nil, fmt.Errorf("wevtapi.EvtNext failed: %v", err)
	}

	// Event handles must be closed after they are returned by EvtNext whether or not we use them.
	defer func() {
		for _, event := range events[:returned] {
			Close(event)
		}
	}()

	// Render events.
	var renderedEvents []string
	for _, event := range events[:returned] {
		// Render the basic XML representation of the event.
		fragment, err := RenderFragment(event, wevtapi.EvtRenderEventXml)
		if err != nil {
			log.Errorf("Failed to render event with EvtRenderEventXml, skipping: %v", err)
			continue
		}

		// Attempt to render the full event using the basic event.
		renderedEvent, err := RenderFormattedMessageXML(event, fragment, locale, publisherCache)
		if err != nil {
			log.Errorf("Failed to fully render event, returning fragment: %v\n%v", err, fragment)
			renderedEvent = fragment
		}
		renderedEvents = append(renderedEvents, renderedEvent)
	}

	// If a bookmark is used in the configuration, update it.
	if config.Bookmark != 0 {
		err = wevtapi.EvtUpdateBookmark(config.Bookmark, events[returned-1])
		if err != nil {
			return nil, fmt.Errorf("wevtapi.EvtUpdateBookmark failed: %v", err)
		}
	}

	return renderedEvents, err
}

// RenderFragment renders a Windows Event Log fragment according to the specified flag.
// Supports rendering events and bookmarks as UTF8 formatted XML strings.
func RenderFragment(fragment windows.Handle, flag uint32) (string, error) {
	var bufferUsed uint32
	var propertyCount uint32

	// Call EvtRender with a null buffer to get the required buffer size.
	err := wevtapi.EvtRender(
		0,
		fragment,
		flag,
		0,
		nil,
		&bufferUsed,
		&propertyCount)
	if err != syscall.ERROR_INSUFFICIENT_BUFFER {
		return "", fmt.Errorf("wevtapi.EvtRender failed: %v", err)
	}

	// Create a buffer based on the buffer size required.
	buf := make([]uint16, bufferUsed/2)

	// Render the fragment according to the flag.
	err = wevtapi.EvtRender(
		0,
		fragment,
		flag,
		bufferUsed,
		unsafe.Pointer(&buf[0]),
		&bufferUsed,
		&propertyCount)
	if err != nil {
		return "", fmt.Errorf("wevtapi.EvtRender failed: %v", err)
	}

	return syscall.UTF16ToString(buf), nil
}

// RenderFormattedMessageXML renders a Windows Event Log event as a UTF8 formatted XML string.
// This includes the RenderingInfo node parsed by leveraging the event publisher and desired
// locale (LCID). Returns the original raw XML if a publisher for the event is unavailable.
func RenderFormattedMessageXML(event windows.Handle, renderedEvent string, locale uint32, cache map[string]windows.Handle) (string, error) {
	// Find the event publisher using the raw event XML.
	re := regexp.MustCompile(`Provider Name='(.*?)\'`)
	publisherMatch := re.FindStringSubmatch(renderedEvent)
	if len(publisherMatch) < 2 {
		return "", fmt.Errorf("RenderFormattedMessageXML: no publisher name found in event")
	}
	publisherName := publisherMatch[1]

	// Lookup publisher metadata.
	var pubHandle windows.Handle
	if val, ok := cache[publisherName]; ok {
		if val == windows.InvalidHandle {
			// We already got ERROR_FILE_NOT_FOUND for this publisher.
			return renderedEvent, nil
		}
		pubHandle = val
	} else {
		var err error
		pubHandle, err = OpenPublisherMetadata(localMachine, publisherName, locale)
		// If there is no publisher metadata available return the original event.
		if err == syscall.ERROR_FILE_NOT_FOUND {
			cache[publisherName] = windows.InvalidHandle
			return renderedEvent, nil
		} else if err != nil {
			return "", fmt.Errorf("OpenPublisherMetadata failed: %v", err)
		}
		cache[publisherName] = pubHandle
	}

	// Call EvtFormatMessage with a null buffer to get the required buffer size.
	var bufferUsed uint32
	err := wevtapi.EvtFormatMessage(
		pubHandle,                   // Handle to provider metadata.
		event,                       // Handle to an event.
		0,                           // Resource identifier of the message string. Null if flag isn't EvtFormatMessageId.
		0,                           // Number of values in the values parameter.
		0,                           // An array of insertion values to be used when formatting the event string. Typically set to null.
		wevtapi.EvtFormatMessageXml, // Format message as an XML string.
		0,                           // Size of buffer.
		nil,                         // Null buffer.
		&bufferUsed)                 // Get the required buffer size.
	if err != syscall.ERROR_INSUFFICIENT_BUFFER {
		return "", fmt.Errorf("wevtapi.EvtFormatMessage failed to get buffer size: %v", err)
	}

	buf := make([]uint16, bufferUsed/2)

	// Render the event as a formatted XML string with RenderingInfo node.
	err = wevtapi.EvtFormatMessage(pubHandle, event, 0, 0, 0, wevtapi.EvtFormatMessageXml,
		bufferUsed, (*byte)(unsafe.Pointer(&buf[0])), &bufferUsed)
	if err != nil {
		return "", fmt.Errorf("wevtapi.EvtFormatMessage failed to render events as formatted XML: %v", err)
	}

	return syscall.UTF16ToString(buf), nil
}

// Subscribe initializes a subscription and returns a handle to the subscription.
// Close must be called on the returned handle when finished.
func Subscribe(config *SubscribeConfig) (windows.Handle, error) {
	// Initialize the subscription.
	subscription, err := wevtapi.EvtSubscribe(
		config.Session,
		config.SignalEvent,
		config.ChannelPath,
		config.Query,
		config.Bookmark,
		config.Context,
		config.Callback,
		config.Flags)
	if err != nil {
		return 0, fmt.Errorf("wevtapi.EvtSubscribe failed: %v", err)
	}

	return subscription, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/lambda"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsLambdaEventSourceMapping() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsLambdaEventSourceMappingCreate,
		Read:   resourceAwsLambdaEventSourceMappingRead,
		Update: resourceAwsLambdaEventSourceMappingUpdate,
		Delete: resourceAwsLambdaEventSourceMappingDelete,

		Schema: map[string]*schema.Schema{
			"event_source_arn": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"function_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"starting_position": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"batch_size": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Default:  100,
			},
			"enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},
			"function_arn": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"last_modified": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"last_processing_result": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"state_transition_reason": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"uuid": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

// resourceAwsLambdaEventSourceMappingCreate maps to:
// CreateEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	functionName := d.Get("function_name").(string)
	eventSourceArn := d.Get("event_source_arn").(string)

	log.Printf("[DEBUG] Creating Lambda event source mapping: source %s to function %s", eventSourceArn, functionName)

	params := &lambda.CreateEventSourceMappingInput{
		EventSourceArn:   aws.String(eventSourceArn),
		FunctionName:     aws.String(functionName),
		StartingPosition: aws.String(d.Get("starting_position").(string)),
		BatchSize:        aws.Int64(int64(d.Get("batch_size").(int))),
		Enabled:          aws.Bool(d.Get("enabled").(bool)),
	}

	err := resource.Retry(1*time.Minute, func() error {
		eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params)
		if err != nil {
			if awserr, ok := err.(awserr.Error); ok {
				if awserr.Code() == "InvalidParameterValueException" {
					// Retryable
					return awserr
				}
			}
			// Not retryable
			return resource.RetryError{Err: err}
		}
		// No error
		d.Set("uuid", eventSourceMappingConfiguration.UUID)
		d.SetId(*eventSourceMappingConfiguration.UUID)
		return nil
	})

	if err != nil {
		return fmt.Errorf("Error creating Lambda event source mapping: %s", err)
	}

	return resourceAwsLambdaEventSourceMappingRead(d, meta)
}

// resourceAwsLambdaEventSourceMappingRead maps to:
// GetEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	log.Printf("[DEBUG] Fetching Lambda event source mapping: %s", d.Id())

	params := &lambda.GetEventSourceMappingInput{
		UUID: aws.String(d.Id()),
	}

	eventSourceMappingConfiguration, err := conn.GetEventSourceMapping(params)
	if err != nil {
		return err
	}

	d.Set("batch_size", eventSourceMappingConfiguration.BatchSize)
	d.Set("event_source_arn", eventSourceMappingConfiguration.EventSourceArn)
	d.Set("function_arn", eventSourceMappingConfiguration.FunctionArn)
	d.Set("last_modified", eventSourceMappingConfiguration.LastModified)
	d.Set("last_processing_result", eventSourceMappingConfiguration.LastProcessingResult)
	d.Set("state", eventSourceMappingConfiguration.State)
	d.Set("state_transition_reason", eventSourceMappingConfiguration.StateTransitionReason)
	d.Set("uuid", eventSourceMappingConfiguration.UUID)

	return nil
}

// resourceAwsLambdaEventSourceMappingDelete maps to:
// DeleteEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	log.Printf("[INFO] Deleting Lambda event source mapping: %s", d.Id())

	params := &lambda.DeleteEventSourceMappingInput{
		UUID: aws.String(d.Id()),
	}

	_, err := conn.DeleteEventSourceMapping(params)
	if err != nil {
		return fmt.Errorf("Error deleting Lambda event source mapping: %s", err)
	}

	d.SetId("")

	return nil
}

// resourceAwsLambdaEventSourceMappingUpdate maps to:
// UpdateEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	log.Printf("[DEBUG] Updating Lambda event source mapping: %s", d.Id())

	params := &lambda.UpdateEventSourceMappingInput{
		UUID:         aws.String(d.Id()),
		BatchSize:    aws.Int64(int64(d.Get("batch_size").(int))),
		FunctionName: aws.String(d.Get("function_name").(string)),
		Enabled:      aws.Bool(d.Get("enabled").(bool)),
	}

	err := resource.Retry(1*time.Minute, func() error {
		_, err := conn.UpdateEventSourceMapping(params)
		if err != nil {
			if awserr, ok := err.(awserr.Error); ok {
				if awserr.Code() == "InvalidParameterValueException" {
					// Retryable
					return awserr
				}
			}
			// Not retryable
			return resource.RetryError{Err: err}
		}
		// No error
		return nil
	})

	if err != nil {
		return fmt.Errorf("Error updating Lambda event source mapping: %s", err)
	}

	return resourceAwsLambdaEventSourceMappingRead(d, meta)
}
<commit_msg>document why we retry in lambda source mapping<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/lambda"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsLambdaEventSourceMapping() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsLambdaEventSourceMappingCreate,
		Read:   resourceAwsLambdaEventSourceMappingRead,
		Update: resourceAwsLambdaEventSourceMappingUpdate,
		Delete: resourceAwsLambdaEventSourceMappingDelete,

		Schema: map[string]*schema.Schema{
			"event_source_arn": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"function_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"starting_position": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"batch_size": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Default:  100,
			},
			"enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},
			"function_arn": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"last_modified": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"last_processing_result": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"state_transition_reason": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"uuid": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

// resourceAwsLambdaEventSourceMappingCreate maps to:
// CreateEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	functionName := d.Get("function_name").(string)
	eventSourceArn := d.Get("event_source_arn").(string)

	log.Printf("[DEBUG] Creating Lambda event source mapping: source %s to function %s", eventSourceArn, functionName)

	params := &lambda.CreateEventSourceMappingInput{
		EventSourceArn:   aws.String(eventSourceArn),
		FunctionName:     aws.String(functionName),
		StartingPosition: aws.String(d.Get("starting_position").(string)),
		BatchSize:        aws.Int64(int64(d.Get("batch_size").(int))),
		Enabled:          aws.Bool(d.Get("enabled").(bool)),
	}

	// IAM profiles and roles can take some time to propagate in AWS:
	//  http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console
	// Error creating Lambda function: InvalidParameterValueException: The
	// function defined for the task cannot be assumed by Lambda.
	//
	// The role may exist, but the permissions may not have propagated, so we
	// retry
	err := resource.Retry(1*time.Minute, func() error {
		eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params)
		if err != nil {
			if awserr, ok := err.(awserr.Error); ok {
				if awserr.Code() == "InvalidParameterValueException" {
					// Retryable
					return awserr
				}
			}
			// Not retryable
			return resource.RetryError{Err: err}
		}
		// No error
		d.Set("uuid", eventSourceMappingConfiguration.UUID)
		d.SetId(*eventSourceMappingConfiguration.UUID)
		return nil
	})

	if err != nil {
		return fmt.Errorf("Error creating Lambda event source mapping: %s", err)
	}

	return resourceAwsLambdaEventSourceMappingRead(d, meta)
}

// resourceAwsLambdaEventSourceMappingRead maps to:
// GetEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	log.Printf("[DEBUG] Fetching Lambda event source mapping: %s", d.Id())

	params := &lambda.GetEventSourceMappingInput{
		UUID: aws.String(d.Id()),
	}

	eventSourceMappingConfiguration, err := conn.GetEventSourceMapping(params)
	if err != nil {
		return err
	}

	d.Set("batch_size", eventSourceMappingConfiguration.BatchSize)
	d.Set("event_source_arn", eventSourceMappingConfiguration.EventSourceArn)
	d.Set("function_arn", eventSourceMappingConfiguration.FunctionArn)
	d.Set("last_modified", eventSourceMappingConfiguration.LastModified)
	d.Set("last_processing_result", eventSourceMappingConfiguration.LastProcessingResult)
	d.Set("state", eventSourceMappingConfiguration.State)
	d.Set("state_transition_reason", eventSourceMappingConfiguration.StateTransitionReason)
	d.Set("uuid", eventSourceMappingConfiguration.UUID)

	return nil
}

// resourceAwsLambdaEventSourceMappingDelete maps to:
// DeleteEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	log.Printf("[INFO] Deleting Lambda event source mapping: %s", d.Id())

	params := &lambda.DeleteEventSourceMappingInput{
		UUID: aws.String(d.Id()),
	}

	_, err := conn.DeleteEventSourceMapping(params)
	if err != nil {
		return fmt.Errorf("Error deleting Lambda event source mapping: %s", err)
	}

	d.SetId("")

	return nil
}

// resourceAwsLambdaEventSourceMappingUpdate maps to:
// UpdateEventSourceMapping in the API / SDK
func resourceAwsLambdaEventSourceMappingUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).lambdaconn

	log.Printf("[DEBUG] Updating Lambda event source mapping: %s", d.Id())

	params := &lambda.UpdateEventSourceMappingInput{
		UUID:         aws.String(d.Id()),
		BatchSize:    aws.Int64(int64(d.Get("batch_size").(int))),
		FunctionName: aws.String(d.Get("function_name").(string)),
		Enabled:      aws.Bool(d.Get("enabled").(bool)),
	}

	err := resource.Retry(1*time.Minute, func() error {
		_, err := conn.UpdateEventSourceMapping(params)
		if err != nil {
			if awserr, ok := err.(awserr.Error); ok {
				if awserr.Code() == "InvalidParameterValueException" {
					// Retryable
					return awserr
				}
			}
			// Not retryable
			return resource.RetryError{Err: err}
		}
		// No error
		return nil
	})

	if err != nil {
		return fmt.Errorf("Error updating Lambda event source mapping: %s", err)
	}

	return resourceAwsLambdaEventSourceMappingRead(d, meta)
}
<|endoftext|>