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

package defaultrolemanager

import (
	"fmt"
	"strings"
	"sync"

	"github.com/casbin/casbin/v2/errors"
	"github.com/casbin/casbin/v2/log"
	"github.com/casbin/casbin/v2/rbac"
	"github.com/casbin/casbin/v2/util"
)

const defaultDomain string = ""
const defaultSeparator = "::"

type MatchingFunc func(arg1, arg2 string) bool

// RoleManager provides a default implementation for the RoleManager interface
type RoleManager struct {
	roles              *Roles
	domains            map[string]struct{}
	maxHierarchyLevel  int
	hasPattern         bool
	matchingFunc       MatchingFunc
	hasDomainPattern   bool
	domainMatchingFunc MatchingFunc

	logger log.Logger
}

// NewRoleManager is the constructor for creating an instance of the
// default RoleManager implementation.
func NewRoleManager(maxHierarchyLevel int) rbac.RoleManager {
	rm := RoleManager{}
	rm.roles = &Roles{sync.Map{}}
	rm.domains = make(map[string]struct{})
	rm.maxHierarchyLevel = maxHierarchyLevel
	rm.hasPattern = false
	rm.hasDomainPattern = false

	rm.SetLogger(&log.DefaultLogger{})

	return &rm
}

// AddMatchingFunc support use pattern in g
func (rm *RoleManager) AddMatchingFunc(name string, fn MatchingFunc) {
	rm.hasPattern = true
	rm.matchingFunc = fn
}

// AddDomainMatchingFunc support use domain pattern in g
func (rm *RoleManager) AddDomainMatchingFunc(name string, fn MatchingFunc) {
	rm.hasDomainPattern = true
	rm.domainMatchingFunc = fn
}

// SetLogger sets role manager's logger.
func (rm *RoleManager) SetLogger(logger log.Logger) {
	rm.logger = logger
}

// Clear clears all stored data and resets the role manager to the initial state.
func (rm *RoleManager) Clear() error {
	rm.roles = &Roles{sync.Map{}}
	rm.domains = make(map[string]struct{})
	return nil
}

// AddLink adds the inheritance link between role: name1 and role: name2.
// aka role: name1 inherits role: name2.
func (rm *RoleManager) AddLink(name1 string, name2 string, domain ...string) error {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		rm.domains[domain[0]] = struct{}{}
		patternDomain := rm.getPatternDomain(domain[0])

		for _, domain := range patternDomain {
			name1WithDomain := getNameWithDomain(domain, name1)
			name2WithDomain := getNameWithDomain(domain, name2)

			role1 := rm.roles.createRole(name1WithDomain)
			role2 := rm.roles.createRole(name2WithDomain)
			role1.addRole(role2)

			if rm.hasPattern {
				rm.roles.Range(func(key, value interface{}) bool {
					domainPattern, namePattern := getNameAndDomain(key.(string))
					if domainPattern != domain {
						return true
					}
					if rm.matchingFunc(namePattern, name1) && name1 != namePattern {
						valueRole, _ := rm.roles.LoadOrStore(key.(string), newRole(key.(string)))
						valueRole.(*Role).addRole(role1)
					}
					if rm.matchingFunc(namePattern, name2) && name2 != namePattern {
						role2.addRole(value.(*Role))
					}
					if rm.matchingFunc(name1, namePattern) && name1 != namePattern {
						valueRole, _ := rm.roles.LoadOrStore(key.(string), newRole(key.(string)))
						valueRole.(*Role).addRole(role1)
					}
					if rm.matchingFunc(name2, namePattern) && name2 != namePattern {
						role2.addRole(value.(*Role))
					}
					return true
				})
			}
		}
		return nil
	default:
		return errors.ERR_DOMAIN_PARAMETER
	}

}

// DeleteLink deletes the inheritance link between role: name1 and role: name2.
// aka role: name1 does not inherit role: name2 any more.
func (rm *RoleManager) DeleteLink(name1 string, name2 string, domain ...string) error {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		name1WithDomain := getNameWithDomain(domain[0], name1)
		name2WithDomain := getNameWithDomain(domain[0], name2)

		_, ok1 := rm.roles.Load(name1WithDomain)
		_, ok2 := rm.roles.Load(name2WithDomain)
		if !ok1 || !ok2 {
			return errors.ERR_NAMES12_NOT_FOUND
		}

		role1 := rm.roles.createRole(name1WithDomain)
		role2 := rm.roles.createRole(name2WithDomain)
		role1.deleteRole(role2)
		return nil
	default:
		return errors.ERR_DOMAIN_PARAMETER
	}
}

func (rm *RoleManager) getPatternDomain(domain string) []string {
	matchedDomains := []string{domain}
	if rm.hasDomainPattern {
		for domainPattern := range rm.domains {
			if domain != domainPattern && rm.domainMatchingFunc(domain, domainPattern) {
				matchedDomains = append(matchedDomains, domainPattern)
			}
		}
	}
	return matchedDomains
}

// HasLink determines whether role: name1 inherits role: name2.
func (rm *RoleManager) HasLink(name1 string, name2 string, domain ...string) (bool, error) {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		if name1 == name2 {
			return true, nil
		}

		matchedDomain := rm.getPatternDomain(domain[0])

		for _, domain := range matchedDomain {
			if !rm.roles.hasRole(domain, name1, rm.matchingFunc) || !rm.roles.hasRole(domain, name2, rm.matchingFunc) {
				continue
			}

			name1WithDomain := getNameWithDomain(domain, name1)
			name2WithDomain := getNameWithDomain(domain, name2)

			if rm.hasPattern {
				flag := false
				rm.roles.Range(func(key, value interface{}) bool {
					nameWithDomain := key.(string)
					_, name := getNameAndDomain(nameWithDomain)
					if rm.matchingFunc(name1, name) && value.(*Role).hasRoleWithMatchingFunc(domain, name2, rm.maxHierarchyLevel, rm.matchingFunc) {
						flag = true
						return false
					}
					return true
				})
				if flag {
					return true, nil
				}
			} else {
				role1 := rm.roles.createRole(name1WithDomain)
				result := role1.hasRole(name2WithDomain, rm.maxHierarchyLevel)
				if result {
					return true, nil
				}
			}
		}
		return false, nil
	default:
		return false, errors.ERR_DOMAIN_PARAMETER
	}
}

// GetRoles gets the roles that a subject inherits.
func (rm *RoleManager) GetRoles(name string, domain ...string) ([]string, error) {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		patternDomain := rm.getPatternDomain(domain[0])

		var gottenRoles []string
		for _, domain := range patternDomain {
			nameWithDomain := getNameWithDomain(domain, name)
			if !rm.roles.hasRole(domain, name, rm.matchingFunc) {
				continue
			}
			gottenRoles = append(gottenRoles, rm.roles.createRole(nameWithDomain).getRoles()...)
		}
		gottenRoles = util.RemoveDuplicateElement(gottenRoles)
		return gottenRoles, nil
	default:
		return nil, errors.ERR_DOMAIN_PARAMETER
	}
}

// GetUsers gets the users that inherits a subject.
// domain is an unreferenced parameter here, may be used in other implementations.
func (rm *RoleManager) GetUsers(name string, domain ...string) ([]string, error) {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		patternDomain := rm.getPatternDomain(domain[0])

		var names []string
		for _, domain := range patternDomain {
			nameWithDomain := getNameWithDomain(domain, name)
			if !rm.roles.hasRole(domain, name, rm.domainMatchingFunc) {
				return nil, errors.ERR_NAME_NOT_FOUND
			}

			rm.roles.Range(func(_, value interface{}) bool {
				role := value.(*Role)
				if role.hasDirectRole(nameWithDomain) {
					_, roleName := getNameAndDomain(role.nameWithDomain)
					names = append(names, roleName)
				}
				return true
			})
		}

		return names, nil
	default:
		return nil, errors.ERR_DOMAIN_PARAMETER
	}
}

// PrintRoles prints all the roles to log.
func (rm *RoleManager) PrintRoles() error {
	if !(rm.logger).IsEnabled() {
		return nil
	}

	var roles []string
	rm.roles.Range(func(_, value interface{}) bool {
		if text := value.(*Role).toString(); text != "" {
			roles = append(roles, text)
		}
		return true
	})

	rm.logger.LogRole(roles)
	return nil
}

// Roles represents all roles in a domain
type Roles struct {
	sync.Map
}

func (roles *Roles) hasRole(domain, name string, matchingFunc MatchingFunc) bool {
	var ok bool
	if matchingFunc != nil {
		roles.Range(func(key, value interface{}) bool {
			domainPattern, namePattern := getNameAndDomain(key.(string))
			if domainPattern == domain && matchingFunc(name, namePattern) {
				ok = true
			}
			return true
		})
	} else {
		_, ok = roles.Load(getNameWithDomain(domain, name))
	}

	return ok
}

func (roles *Roles) createRole(name string) *Role {
	role, _ := roles.LoadOrStore(name, newRole(name))
	return role.(*Role)
}

// Role represents the data structure for a role in RBAC.
type Role struct {
	nameWithDomain string
	roles          []*Role
}

func newRole(name string) *Role {
	r := Role{}
	r.nameWithDomain = name
	return &r
}

func (r *Role) addRole(role *Role) {
	// determine whether this role has been added
	for _, rr := range r.roles {
		if rr.nameWithDomain == role.nameWithDomain {
			return
		}
	}

	r.roles = append(r.roles, role)
}

func (r *Role) deleteRole(role *Role) {
	for i, rr := range r.roles {
		if rr.nameWithDomain == role.nameWithDomain {
			r.roles = append(r.roles[:i], r.roles[i+1:]...)
			return
		}
	}
}

func (r *Role) hasRole(nameWithDomain string, hierarchyLevel int) bool {
	if r.hasDirectRole(nameWithDomain) {
		return true
	}

	if hierarchyLevel <= 0 {
		return false
	}

	for _, role := range r.roles {
		if role.hasRole(nameWithDomain, hierarchyLevel-1) {
			return true
		}
	}
	return false
}

func (r *Role) hasRoleWithMatchingFunc(domain, name string, hierarchyLevel int, matchingFunc MatchingFunc) bool {
	if r.hasDirectRoleWithMatchingFunc(domain, name, matchingFunc) {
		return true
	}

	if hierarchyLevel <= 0 {
		return false
	}

	for _, role := range r.roles {
		if role.hasRoleWithMatchingFunc(domain, name, hierarchyLevel-1, matchingFunc) {
			return true
		}
	}
	return false
}

func (r *Role) hasDirectRole(nameWithDomain string) bool {
	for _, role := range r.roles {
		if role.nameWithDomain == nameWithDomain {
			return true
		}
	}

	return false
}

func (r *Role) hasDirectRoleWithMatchingFunc(domain, name string, matchingFunc MatchingFunc) bool {
	roleWithDomain := getNameWithDomain(domain, name)
	for _, role := range r.roles {
		roleDomain, roleName := getNameAndDomain(role.nameWithDomain)
		if role.nameWithDomain == roleWithDomain || (matchingFunc(name, roleName) && roleDomain == domain) {
			return true
		}
	}

	return false
}

func (r *Role) toString() string {
	if len(r.roles) == 0 {
		return ""
	}

	var sb strings.Builder
	sb.WriteString(r.nameWithDomain)
	sb.WriteString(" < ")
	if len(r.roles) != 1 {
		sb.WriteString("(")
	}

	for i, role := range r.roles {
		if i == 0 {
			sb.WriteString(role.nameWithDomain)
		} else {
			sb.WriteString(", ")
			sb.WriteString(role.nameWithDomain)
		}
	}

	if len(r.roles) != 1 {
		sb.WriteString(")")
	}

	return sb.String()
}

func (r *Role) getRoles() []string {
	names := []string{}
	for _, role := range r.roles {
		_, roleName := getNameAndDomain(role.nameWithDomain)
		names = append(names, roleName)
	}
	return names
}

func getNameWithDomain(domain, name string) string {
	if domain == "" {
		return name
	}
	return fmt.Sprintf("%s%s%s", domain, defaultSeparator, name)
}

func getNameAndDomain(domainAndName string) (string, string) {
	t := strings.Split(domainAndName, defaultSeparator)
	if len(t) == 1 {
		return defaultDomain, t[0]
	}
	return t[0], t[1]
}
<commit_msg>refactor!: return a *RoleManager instead of the interface<commit_after>// Copyright 2017 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package defaultrolemanager

import (
	"fmt"
	"strings"
	"sync"

	"github.com/casbin/casbin/v2/errors"
	"github.com/casbin/casbin/v2/log"
	"github.com/casbin/casbin/v2/util"
)

const defaultDomain string = ""
const defaultSeparator = "::"

type MatchingFunc func(arg1, arg2 string) bool

// RoleManager provides a default implementation for the RoleManager interface
type RoleManager struct {
	roles              *Roles
	domains            map[string]struct{}
	maxHierarchyLevel  int
	hasPattern         bool
	matchingFunc       MatchingFunc
	hasDomainPattern   bool
	domainMatchingFunc MatchingFunc

	logger log.Logger
}

// NewRoleManager is the constructor for creating an instance of the
// default RoleManager implementation.
func NewRoleManager(maxHierarchyLevel int) *RoleManager {
	rm := RoleManager{}
	rm.roles = &Roles{sync.Map{}}
	rm.domains = make(map[string]struct{})
	rm.maxHierarchyLevel = maxHierarchyLevel
	rm.hasPattern = false
	rm.hasDomainPattern = false

	rm.SetLogger(&log.DefaultLogger{})

	return &rm
}

// AddMatchingFunc support use pattern in g
func (rm *RoleManager) AddMatchingFunc(name string, fn MatchingFunc) {
	rm.hasPattern = true
	rm.matchingFunc = fn
}

// AddDomainMatchingFunc support use domain pattern in g
func (rm *RoleManager) AddDomainMatchingFunc(name string, fn MatchingFunc) {
	rm.hasDomainPattern = true
	rm.domainMatchingFunc = fn
}

// SetLogger sets role manager's logger.
func (rm *RoleManager) SetLogger(logger log.Logger) {
	rm.logger = logger
}

// Clear clears all stored data and resets the role manager to the initial state.
func (rm *RoleManager) Clear() error {
	rm.roles = &Roles{sync.Map{}}
	rm.domains = make(map[string]struct{})
	return nil
}

// AddLink adds the inheritance link between role: name1 and role: name2.
// aka role: name1 inherits role: name2.
func (rm *RoleManager) AddLink(name1 string, name2 string, domain ...string) error {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		rm.domains[domain[0]] = struct{}{}
		patternDomain := rm.getPatternDomain(domain[0])

		for _, domain := range patternDomain {
			name1WithDomain := getNameWithDomain(domain, name1)
			name2WithDomain := getNameWithDomain(domain, name2)

			role1 := rm.roles.createRole(name1WithDomain)
			role2 := rm.roles.createRole(name2WithDomain)
			role1.addRole(role2)

			if rm.hasPattern {
				rm.roles.Range(func(key, value interface{}) bool {
					domainPattern, namePattern := getNameAndDomain(key.(string))
					if domainPattern != domain {
						return true
					}
					if rm.matchingFunc(namePattern, name1) && name1 != namePattern {
						valueRole, _ := rm.roles.LoadOrStore(key.(string), newRole(key.(string)))
						valueRole.(*Role).addRole(role1)
					}
					if rm.matchingFunc(namePattern, name2) && name2 != namePattern {
						role2.addRole(value.(*Role))
					}
					if rm.matchingFunc(name1, namePattern) && name1 != namePattern {
						valueRole, _ := rm.roles.LoadOrStore(key.(string), newRole(key.(string)))
						valueRole.(*Role).addRole(role1)
					}
					if rm.matchingFunc(name2, namePattern) && name2 != namePattern {
						role2.addRole(value.(*Role))
					}
					return true
				})
			}
		}
		return nil
	default:
		return errors.ERR_DOMAIN_PARAMETER
	}

}

// DeleteLink deletes the inheritance link between role: name1 and role: name2.
// aka role: name1 does not inherit role: name2 any more.
func (rm *RoleManager) DeleteLink(name1 string, name2 string, domain ...string) error {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		name1WithDomain := getNameWithDomain(domain[0], name1)
		name2WithDomain := getNameWithDomain(domain[0], name2)

		_, ok1 := rm.roles.Load(name1WithDomain)
		_, ok2 := rm.roles.Load(name2WithDomain)
		if !ok1 || !ok2 {
			return errors.ERR_NAMES12_NOT_FOUND
		}

		role1 := rm.roles.createRole(name1WithDomain)
		role2 := rm.roles.createRole(name2WithDomain)
		role1.deleteRole(role2)
		return nil
	default:
		return errors.ERR_DOMAIN_PARAMETER
	}
}

func (rm *RoleManager) getPatternDomain(domain string) []string {
	matchedDomains := []string{domain}
	if rm.hasDomainPattern {
		for domainPattern := range rm.domains {
			if domain != domainPattern && rm.domainMatchingFunc(domain, domainPattern) {
				matchedDomains = append(matchedDomains, domainPattern)
			}
		}
	}
	return matchedDomains
}

// HasLink determines whether role: name1 inherits role: name2.
func (rm *RoleManager) HasLink(name1 string, name2 string, domain ...string) (bool, error) {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		if name1 == name2 {
			return true, nil
		}

		matchedDomain := rm.getPatternDomain(domain[0])

		for _, domain := range matchedDomain {
			if !rm.roles.hasRole(domain, name1, rm.matchingFunc) || !rm.roles.hasRole(domain, name2, rm.matchingFunc) {
				continue
			}

			name1WithDomain := getNameWithDomain(domain, name1)
			name2WithDomain := getNameWithDomain(domain, name2)

			if rm.hasPattern {
				flag := false
				rm.roles.Range(func(key, value interface{}) bool {
					nameWithDomain := key.(string)
					_, name := getNameAndDomain(nameWithDomain)
					if rm.matchingFunc(name1, name) && value.(*Role).hasRoleWithMatchingFunc(domain, name2, rm.maxHierarchyLevel, rm.matchingFunc) {
						flag = true
						return false
					}
					return true
				})
				if flag {
					return true, nil
				}
			} else {
				role1 := rm.roles.createRole(name1WithDomain)
				result := role1.hasRole(name2WithDomain, rm.maxHierarchyLevel)
				if result {
					return true, nil
				}
			}
		}
		return false, nil
	default:
		return false, errors.ERR_DOMAIN_PARAMETER
	}
}

// GetRoles gets the roles that a subject inherits.
func (rm *RoleManager) GetRoles(name string, domain ...string) ([]string, error) {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		patternDomain := rm.getPatternDomain(domain[0])

		var gottenRoles []string
		for _, domain := range patternDomain {
			nameWithDomain := getNameWithDomain(domain, name)
			if !rm.roles.hasRole(domain, name, rm.matchingFunc) {
				continue
			}
			gottenRoles = append(gottenRoles, rm.roles.createRole(nameWithDomain).getRoles()...)
		}
		gottenRoles = util.RemoveDuplicateElement(gottenRoles)
		return gottenRoles, nil
	default:
		return nil, errors.ERR_DOMAIN_PARAMETER
	}
}

// GetUsers gets the users that inherits a subject.
// domain is an unreferenced parameter here, may be used in other implementations.
func (rm *RoleManager) GetUsers(name string, domain ...string) ([]string, error) {
	switch len(domain) {
	case 0:
		domain = []string{defaultDomain}
		fallthrough
	case 1:
		patternDomain := rm.getPatternDomain(domain[0])

		var names []string
		for _, domain := range patternDomain {
			nameWithDomain := getNameWithDomain(domain, name)
			if !rm.roles.hasRole(domain, name, rm.domainMatchingFunc) {
				return nil, errors.ERR_NAME_NOT_FOUND
			}

			rm.roles.Range(func(_, value interface{}) bool {
				role := value.(*Role)
				if role.hasDirectRole(nameWithDomain) {
					_, roleName := getNameAndDomain(role.nameWithDomain)
					names = append(names, roleName)
				}
				return true
			})
		}

		return names, nil
	default:
		return nil, errors.ERR_DOMAIN_PARAMETER
	}
}

// PrintRoles prints all the roles to log.
func (rm *RoleManager) PrintRoles() error {
	if !(rm.logger).IsEnabled() {
		return nil
	}

	var roles []string
	rm.roles.Range(func(_, value interface{}) bool {
		if text := value.(*Role).toString(); text != "" {
			roles = append(roles, text)
		}
		return true
	})

	rm.logger.LogRole(roles)
	return nil
}

// Roles represents all roles in a domain
type Roles struct {
	sync.Map
}

func (roles *Roles) hasRole(domain, name string, matchingFunc MatchingFunc) bool {
	var ok bool
	if matchingFunc != nil {
		roles.Range(func(key, value interface{}) bool {
			domainPattern, namePattern := getNameAndDomain(key.(string))
			if domainPattern == domain && matchingFunc(name, namePattern) {
				ok = true
			}
			return true
		})
	} else {
		_, ok = roles.Load(getNameWithDomain(domain, name))
	}

	return ok
}

func (roles *Roles) createRole(name string) *Role {
	role, _ := roles.LoadOrStore(name, newRole(name))
	return role.(*Role)
}

// Role represents the data structure for a role in RBAC.
type Role struct {
	nameWithDomain string
	roles          []*Role
}

func newRole(name string) *Role {
	r := Role{}
	r.nameWithDomain = name
	return &r
}

func (r *Role) addRole(role *Role) {
	// determine whether this role has been added
	for _, rr := range r.roles {
		if rr.nameWithDomain == role.nameWithDomain {
			return
		}
	}

	r.roles = append(r.roles, role)
}

func (r *Role) deleteRole(role *Role) {
	for i, rr := range r.roles {
		if rr.nameWithDomain == role.nameWithDomain {
			r.roles = append(r.roles[:i], r.roles[i+1:]...)
			return
		}
	}
}

func (r *Role) hasRole(nameWithDomain string, hierarchyLevel int) bool {
	if r.hasDirectRole(nameWithDomain) {
		return true
	}

	if hierarchyLevel <= 0 {
		return false
	}

	for _, role := range r.roles {
		if role.hasRole(nameWithDomain, hierarchyLevel-1) {
			return true
		}
	}
	return false
}

func (r *Role) hasRoleWithMatchingFunc(domain, name string, hierarchyLevel int, matchingFunc MatchingFunc) bool {
	if r.hasDirectRoleWithMatchingFunc(domain, name, matchingFunc) {
		return true
	}

	if hierarchyLevel <= 0 {
		return false
	}

	for _, role := range r.roles {
		if role.hasRoleWithMatchingFunc(domain, name, hierarchyLevel-1, matchingFunc) {
			return true
		}
	}
	return false
}

func (r *Role) hasDirectRole(nameWithDomain string) bool {
	for _, role := range r.roles {
		if role.nameWithDomain == nameWithDomain {
			return true
		}
	}

	return false
}

func (r *Role) hasDirectRoleWithMatchingFunc(domain, name string, matchingFunc MatchingFunc) bool {
	roleWithDomain := getNameWithDomain(domain, name)
	for _, role := range r.roles {
		roleDomain, roleName := getNameAndDomain(role.nameWithDomain)
		if role.nameWithDomain == roleWithDomain || (matchingFunc(name, roleName) && roleDomain == domain) {
			return true
		}
	}

	return false
}

func (r *Role) toString() string {
	if len(r.roles) == 0 {
		return ""
	}

	var sb strings.Builder
	sb.WriteString(r.nameWithDomain)
	sb.WriteString(" < ")
	if len(r.roles) != 1 {
		sb.WriteString("(")
	}

	for i, role := range r.roles {
		if i == 0 {
			sb.WriteString(role.nameWithDomain)
		} else {
			sb.WriteString(", ")
			sb.WriteString(role.nameWithDomain)
		}
	}

	if len(r.roles) != 1 {
		sb.WriteString(")")
	}

	return sb.String()
}

func (r *Role) getRoles() []string {
	names := []string{}
	for _, role := range r.roles {
		_, roleName := getNameAndDomain(role.nameWithDomain)
		names = append(names, roleName)
	}
	return names
}

func getNameWithDomain(domain, name string) string {
	if domain == "" {
		return name
	}
	return fmt.Sprintf("%s%s%s", domain, defaultSeparator, name)
}

func getNameAndDomain(domainAndName string) (string, string) {
	t := strings.Split(domainAndName, defaultSeparator)
	if len(t) == 1 {
		return defaultDomain, t[0]
	}
	return t[0], t[1]
}
<|endoftext|>


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

/*
Package util/sig is simple sig trap closer
*/

package sig

import (
	"net"
	"os"
	"os/signal"
	"syscall"

	"github.com/simonz05/util/log"
)

type Cleanup func() error

func sigTrapCloser(l net.Listener, cleanups ...Cleanup) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGHUP)

	go func() {
		for _ = range c {
			for _, cb := range cleanups {
				if err := cb(); err != nil {
					log.Error(err)
				}
			}
			l.Close()
			log.Printf("Closed listener %s", l.Addr())
		}
	}()
}
<commit_msg>sig: sigTrapCloser -> TrapCloser<commit_after>// Copyright 2014 Simon Zimmermann. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

/*
Package util/sig is simple sig trap closer
*/

package sig

import (
	"net"
	"os"
	"os/signal"
	"syscall"

	"github.com/simonz05/util/log"
)

type Cleanup func() error

func TrapCloser(l net.Listener, cleanups ...Cleanup) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGHUP)

	go func() {
		for _ = range c {
			for _, cb := range cleanups {
				if err := cb(); err != nil {
					log.Error(err)
				}
			}
			l.Close()
			log.Printf("Closed listener %s", l.Addr())
		}
	}()
}
<|endoftext|>


<commit_before>package flue

// This will convert the TaskGraphStructure into a format suitable for sigmajs
type SigmaNode struct {
	Id    int    // "id": "1",
	Labe  string //"label": "Node 1",
	Color string //"color": "rgb(90,90,90)",
	Size  int    //"size": 100,
	X     int    //"x": 10,
	Y     int    //"y": -10,
	Type  string //"type": "tweetegy"

}

type SigmaEdge struct {
	id     int
	source int
	target int
}
<commit_msg>Added the structure for a sigma json<commit_after>package flue

// This will convert the TaskGraphStructure into a format suitable for sigmajs
type SigmaNode struct {
	Id    int    // "id": "1",
	Labe  string //"label": "Node 1",
	Color string //"color": "rgb(90,90,90)",
	Size  int    //"size": 100,
	X     int    //"x": 10,
	Y     int    //"y": -10,
	Type  string //"type": "tweetegy"

}

type SigmaEdge struct {
	Id     int
	Source int
	Target int
}

type SigmaJson struct {
	Edges []SigmaEdge
	Nodes []SigmaNode
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"encoding/hex"
	"flag"
	"github.com/jeffail/tunny"
	csv "github.com/whosonfirst/go-whosonfirst-csv"
	log "github.com/whosonfirst/go-whosonfirst-log"
	"io"
	"io/ioutil"
	golog "log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

type WOFClone struct {
	Source    string
	Dest      string
	Count     int64
	Success   int64
	Error     int64
	Skipped   int64
	Scheduled int64
	Completed int64
	client    *http.Client
	logger    *log.WOFLogger
	pool      *tunny.WorkPool
}

func NewWOFClone(source string, dest string, procs int, logger *log.WOFLogger) *WOFClone {

	// cd := &sync.Cond{L: &sync.Mutex{}}

	cl := &http.Client{}

	runtime.GOMAXPROCS(procs)

	pool, _ := tunny.CreatePoolGeneric(procs).Open()

	c := WOFClone{
		Count:   0,
		Success: 0,
		Error:   0,
		Skipped: 0,
		Source:  source,
		Dest:    dest,
		logger:  logger,
		client:  cl,
		pool:    pool,
	}

	return &c
}

func (c *WOFClone) CloneMetaFile(file string) error {

	abs_path, _ := filepath.Abs(file)
	// c.logger.Debug("Parse meta file %s", abs_path)

	reader, read_err := csv.NewDictReader(abs_path)

	if read_err != nil {
		c.logger.Error("Failed to read %s, because %v", abs_path, read_err)
		return read_err
	}

	wg := new(sync.WaitGroup)

	for {
		row, err := reader.Read()

		if err == io.EOF {
			break
		}

		if err != nil {
			return err
		}

		rel_path, ok := row["path"]

		if !ok {
			continue
		}

		wg.Add(1)
		atomic.AddInt64(&c.Scheduled, 1)

		go func() {

			defer wg.Done()

			_, err = c.pool.SendWork(func() {

				cl_err := c.ClonePath(rel_path, true)

				if cl_err != nil {
					atomic.AddInt64(&c.Error, 1)
				} else {
					atomic.AddInt64(&c.Success, 1)
				}

				atomic.AddInt64(&c.Completed, 1)
				c.Status()
			})

		}()
	}

	wg.Wait()
	return nil
}

func (c *WOFClone) ClonePath(rel_path string, ensure_changes bool) error {

	atomic.AddInt64(&c.Count, 1)

	remote := c.Source + rel_path
	local := path.Join(c.Dest, rel_path)

	_, err := os.Stat(local)

	if !os.IsNotExist(err) && ensure_changes {

		change, _ := c.HasChanged(local, remote)

		if !change {

			c.logger.Debug("%s has not changed so skipping", local)
			atomic.AddInt64(&c.Skipped, 1)
			return nil
		}

	}

	process_err := c.Process(remote, local)

	if process_err != nil {
		atomic.AddInt64(&c.Error, 1)
		return process_err
	}

	return nil
}

func (c *WOFClone) HasChanged(local string, remote string) (bool, error) {

	change := true

	body, err := ioutil.ReadFile(local)

	if err != nil {
		c.logger.Error("Failed to read %s, becase %v", local, err)
		golog.Fatal(err)
		return change, err
	}

	hash := md5.Sum(body)
	local_hash := hex.EncodeToString(hash[:])

	rsp, err := c.Fetch("HEAD", remote)

	if err != nil {
		return change, err
	}

	defer rsp.Body.Close()

	etag := rsp.Header.Get("Etag")
	remote_hash := strings.Replace(etag, "\"", "", -1)

	if local_hash == remote_hash {
		change = false
	}

	return change, nil
}

func (c *WOFClone) Process(remote string, local string) error {

	c.logger.Debug("fetch %s and store in %s", remote, local)

	local_root := path.Dir(local)

	_, err := os.Stat(local_root)

	if os.IsNotExist(err) {
		c.logger.Info("create %s", local_root)
		os.MkdirAll(local_root, 0755)
	}

	rsp, fetch_err := c.Fetch("GET", remote)

	if fetch_err != nil {
		return fetch_err
	}

	defer rsp.Body.Close()

	contents, read_err := ioutil.ReadAll(rsp.Body)

	if read_err != nil {
		c.logger.Error("failed to read body for %s, because %v", remote, read_err)
		return read_err
	}

	go func() error {

		write_err := ioutil.WriteFile(local, contents, 0644)

		if write_err != nil {
			c.logger.Error("Failed to write %s, because %v", local, write_err)

			atomic.AddInt64(&c.Success, -1)
			atomic.AddInt64(&c.Error, 1)

			return write_err
		}

		c.logger.Debug("Wrote %s to disk", local)
		return nil
	}()

	return nil
}

func (c *WOFClone) Fetch(method string, url string) (*http.Response, error) {

	c.logger.Debug("%s %s", method, url)

	req, _ := http.NewRequest(method, url, nil)
	req.Close = true

	rsp, err := c.client.Do(req)

	if err != nil {
		c.logger.Error("Failed to %s %s, because %v", method, url, err)
		// golog.Fatal(err)
		return nil, err
	}

	return rsp, err
}

func (c *WOFClone) Status() {
	c.logger.Info("scheduled: %d completed: %d success: %d error: %d goroutines: %d", c.Scheduled, c.Completed, c.Success, c.Error, runtime.NumGoroutine())
}

func main() {

	var source = flag.String("source", "https://s3.amazonaws.com/whosonfirst.mapzen.com/data/", "Where to look for files")
	var dest = flag.String("dest", "", "Where to write files")
	var procs = flag.Int("procs", 200, "The number of concurrent processes to clone data with")
	var loglevel = flag.String("loglevel", "info", "The level of detail for logging")

	flag.Parse()
	args := flag.Args()

	writer := io.MultiWriter(os.Stdout)

	lg := log.NewWOFLogger(writer, "[clone] ", *loglevel)

	cl := NewWOFClone(*source, *dest, *procs, lg)

	start := time.Now()

	for _, file := range args {
		cl.CloneMetaFile(file)
	}

	since := time.Since(start)
	secs := float64(since) / 1e9

	cl.logger.Info("processed %d files (ok: %d error: %d skipped: %d) in %f seconds\n", cl.Count, cl.Success, cl.Error, cl.Skipped, secs)
}
<commit_msg>remove log.Fatal<commit_after>package main

import (
	"crypto/md5"
	"encoding/hex"
	"flag"
	"github.com/jeffail/tunny"
	csv "github.com/whosonfirst/go-whosonfirst-csv"
	log "github.com/whosonfirst/go-whosonfirst-log"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

type WOFClone struct {
	Source    string
	Dest      string
	Count     int64
	Success   int64
	Error     int64
	Skipped   int64
	Scheduled int64
	Completed int64
	client    *http.Client
	logger    *log.WOFLogger
	pool      *tunny.WorkPool
}

func NewWOFClone(source string, dest string, procs int, logger *log.WOFLogger) *WOFClone {

	// cd := &sync.Cond{L: &sync.Mutex{}}

	cl := &http.Client{}

	runtime.GOMAXPROCS(procs)

	pool, _ := tunny.CreatePoolGeneric(procs).Open()

	c := WOFClone{
		Count:   0,
		Success: 0,
		Error:   0,
		Skipped: 0,
		Source:  source,
		Dest:    dest,
		logger:  logger,
		client:  cl,
		pool:    pool,
	}

	return &c
}

func (c *WOFClone) CloneMetaFile(file string) error {

	abs_path, _ := filepath.Abs(file)
	// c.logger.Debug("Parse meta file %s", abs_path)

	reader, read_err := csv.NewDictReader(abs_path)

	if read_err != nil {
		c.logger.Error("Failed to read %s, because %v", abs_path, read_err)
		return read_err
	}

	wg := new(sync.WaitGroup)

	for {
		row, err := reader.Read()

		if err == io.EOF {
			break
		}

		if err != nil {
			return err
		}

		rel_path, ok := row["path"]

		if !ok {
			continue
		}

		wg.Add(1)
		atomic.AddInt64(&c.Scheduled, 1)

		go func() {

			defer wg.Done()

			_, err = c.pool.SendWork(func() {

				cl_err := c.ClonePath(rel_path, true)

				if cl_err != nil {
					atomic.AddInt64(&c.Error, 1)
				} else {
					atomic.AddInt64(&c.Success, 1)
				}

				atomic.AddInt64(&c.Completed, 1)
				c.Status()
			})

		}()
	}

	wg.Wait()
	return nil
}

func (c *WOFClone) ClonePath(rel_path string, ensure_changes bool) error {

	atomic.AddInt64(&c.Count, 1)

	remote := c.Source + rel_path
	local := path.Join(c.Dest, rel_path)

	_, err := os.Stat(local)

	if !os.IsNotExist(err) && ensure_changes {

		change, _ := c.HasChanged(local, remote)

		if !change {

			c.logger.Debug("%s has not changed so skipping", local)
			atomic.AddInt64(&c.Skipped, 1)
			return nil
		}

	}

	process_err := c.Process(remote, local)

	if process_err != nil {
		atomic.AddInt64(&c.Error, 1)
		return process_err
	}

	return nil
}

func (c *WOFClone) HasChanged(local string, remote string) (bool, error) {

	change := true

	body, err := ioutil.ReadFile(local)

	if err != nil {
		c.logger.Error("Failed to read %s, becase %v", local, err)
		return change, err
	}

	hash := md5.Sum(body)
	local_hash := hex.EncodeToString(hash[:])

	rsp, err := c.Fetch("HEAD", remote)

	if err != nil {
		return change, err
	}

	defer rsp.Body.Close()

	etag := rsp.Header.Get("Etag")
	remote_hash := strings.Replace(etag, "\"", "", -1)

	if local_hash == remote_hash {
		change = false
	}

	return change, nil
}

func (c *WOFClone) Process(remote string, local string) error {

	c.logger.Debug("fetch %s and store in %s", remote, local)

	local_root := path.Dir(local)

	_, err := os.Stat(local_root)

	if os.IsNotExist(err) {
		c.logger.Info("create %s", local_root)
		os.MkdirAll(local_root, 0755)
	}

	rsp, fetch_err := c.Fetch("GET", remote)

	if fetch_err != nil {
		return fetch_err
	}

	defer rsp.Body.Close()

	contents, read_err := ioutil.ReadAll(rsp.Body)

	if read_err != nil {
		c.logger.Error("failed to read body for %s, because %v", remote, read_err)
		return read_err
	}

	go func() error {

		write_err := ioutil.WriteFile(local, contents, 0644)

		if write_err != nil {
			c.logger.Error("Failed to write %s, because %v", local, write_err)

			atomic.AddInt64(&c.Success, -1)
			atomic.AddInt64(&c.Error, 1)

			return write_err
		}

		c.logger.Debug("Wrote %s to disk", local)
		return nil
	}()

	return nil
}

func (c *WOFClone) Fetch(method string, url string) (*http.Response, error) {

	c.logger.Debug("%s %s", method, url)

	req, _ := http.NewRequest(method, url, nil)
	req.Close = true

	rsp, err := c.client.Do(req)

	if err != nil {
		c.logger.Error("Failed to %s %s, because %v", method, url, err)
		// golog.Fatal(err)
		return nil, err
	}

	return rsp, err
}

func (c *WOFClone) Status() {
	c.logger.Info("scheduled: %d completed: %d success: %d error: %d goroutines: %d", c.Scheduled, c.Completed, c.Success, c.Error, runtime.NumGoroutine())
}

func main() {

	var source = flag.String("source", "https://s3.amazonaws.com/whosonfirst.mapzen.com/data/", "Where to look for files")
	var dest = flag.String("dest", "", "Where to write files")
	var procs = flag.Int("procs", 200, "The number of concurrent processes to clone data with")
	var loglevel = flag.String("loglevel", "info", "The level of detail for logging")

	flag.Parse()
	args := flag.Args()

	writer := io.MultiWriter(os.Stdout)

	lg := log.NewWOFLogger(writer, "[clone] ", *loglevel)

	cl := NewWOFClone(*source, *dest, *procs, lg)

	start := time.Now()

	for _, file := range args {
		cl.CloneMetaFile(file)
	}

	since := time.Since(start)
	secs := float64(since) / 1e9

	cl.logger.Info("processed %d files (ok: %d error: %d skipped: %d) in %f seconds\n", cl.Count, cl.Success, cl.Error, cl.Skipped, secs)
}
<|endoftext|>


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

package gcs

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"

	"github.com/jacobsa/gcloud/httputil"
	"github.com/jacobsa/reqtrace"

	"google.golang.org/api/googleapi"
	storagev1 "google.golang.org/api/storage/v1"
)

// OAuth scopes for GCS. For use with e.g. google.DefaultTokenSource.
const (
	Scope_FullControl = storagev1.DevstorageFullControlScope
	Scope_ReadOnly    = storagev1.DevstorageReadOnlyScope
	Scope_ReadWrite   = storagev1.DevstorageReadWriteScope
)

// Conn represents a connection to GCS, pre-bound with a project ID and
// information required for authorization.
type Conn interface {
	// Return a Bucket object representing the GCS bucket with the given name.
	// Attempt to fail early in the case of bad credentials.
	OpenBucket(
		ctx context.Context,
		name string) (b Bucket, err error)
}

// Configuration accepted by NewConn.
type ConnConfig struct {
	// An oauth2 token source to use for authenticating to GCS.
	//
	// You probably want this one:
	//     http://godoc.org/golang.org/x/oauth2/google#DefaultTokenSource
	TokenSource oauth2.TokenSource

	// The value to set in User-Agent headers for outgoing HTTP requests. If
	// empty, a default will be used.
	UserAgent string

	// The maximum amount of time to spend sleeping in a retry loop with
	// exponential backoff for failed requests. The default of zero disables
	// automatic retries.
	//
	// If you enable automatic retries, beware of the following:
	//
	//  *  Bucket.CreateObject will buffer the entire object contents in memory,
	//     so your object contents must not be too large to fit.
	//
	//  *  Bucket.NewReader needs to perform an additional round trip to GCS in
	//     order to find the latest object generation if you don't specify a
	//     particular generation.
	//
	//  *  Make sure your operations are idempotent, or that your application can
	//     tolerate it if not.
	//
	MaxBackoffSleep time.Duration

	// Loggers for GCS events, and (much more verbose) HTTP requests and
	// responses. If nil, no logging is performed.
	GCSDebugLogger  *log.Logger
	HTTPDebugLogger *log.Logger
}

// Open a connection to GCS.
func NewConn(cfg *ConnConfig) (c Conn, err error) {
	// Fix the user agent if there is none.
	userAgent := cfg.UserAgent
	if userAgent == "" {
		const defaultUserAgent = "github.com-jacobsa-gloud-gcs"
		userAgent = defaultUserAgent
	}

	// Enable HTTP debugging if requested.
	transport := http.DefaultTransport.(httputil.CancellableRoundTripper)
	if cfg.HTTPDebugLogger != nil {
		transport = httputil.DebuggingRoundTripper(transport, cfg.HTTPDebugLogger)
	}

	// Wrap the HTTP transport in an oauth layer.
	if cfg.TokenSource == nil {
		err = errors.New("You must set TokenSource.")
		return
	}

	transport = &oauth2.Transport{
		Source: cfg.TokenSource,
		Base:   transport,
	}

	// Set up the connection.
	c = &conn{
		client:          &http.Client{Transport: transport},
		userAgent:       userAgent,
		maxBackoffSleep: cfg.MaxBackoffSleep,
		debugLogger:     cfg.GCSDebugLogger,
	}

	return
}

type conn struct {
	client          *http.Client
	userAgent       string
	maxBackoffSleep time.Duration
	debugLogger     *log.Logger
}

func (c *conn) OpenBucket(
	ctx context.Context,
	name string) (b Bucket, err error) {
	b = newBucket(c.client, c.userAgent, name)

	// Enable retry loops if requested.
	if c.maxBackoffSleep > 0 {
		// TODO(jacobsa): Show the retries as distinct spans in the trace.
		b = newRetryBucket(c.maxBackoffSleep, b)
	}

	// Enable tracing if appropriate.
	if reqtrace.Enabled() {
		b = &reqtraceBucket{
			Wrapped: b,
		}
	}

	// Print debug output if requested.
	if c.debugLogger != nil {
		b = newDebugBucket(b, c.debugLogger)
	}

	// Attempt to make an innocuous request to the bucket, snooping for HTTP 403
	// errors that indicate bad credentials. This lets us warn the user early in
	// the latter case, with a more helpful message than just "HTTP 403
	// Forbidden". Similarly for bad bucket names that don't collide with another
	// bucket.
	_, err = b.ListObjects(ctx, &ListObjectsRequest{MaxResults: 1})

	if typed, ok := err.(*googleapi.Error); ok {
		switch typed.Code {
		case http.StatusForbidden:
			err = fmt.Errorf(
				"Bad credentials for bucket %q. Check the bucket name and your "+
					"credentials.",
				b.Name())

			return

		case http.StatusNotFound:
			err = fmt.Errorf("Unknown bucket %q", b.Name())
			return
		}
	}

	// Otherwise, don't interfere.
	err = nil

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

package gcs

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"

	"github.com/jacobsa/gcloud/httputil"
	"github.com/jacobsa/reqtrace"

	"google.golang.org/api/googleapi"
	storagev1 "google.golang.org/api/storage/v1"
)

// OAuth scopes for GCS. For use with e.g. google.DefaultTokenSource.
const (
	Scope_FullControl = storagev1.DevstorageFullControlScope
	Scope_ReadOnly    = storagev1.DevstorageReadOnlyScope
	Scope_ReadWrite   = storagev1.DevstorageReadWriteScope
)

// Conn represents a connection to GCS, pre-bound with a project ID and
// information required for authorization.
type Conn interface {
	// Return a Bucket object representing the GCS bucket with the given name.
	// Attempt to fail early in the case of bad credentials.
	OpenBucket(
		ctx context.Context,
		name string) (b Bucket, err error)
}

// Configuration accepted by NewConn.
type ConnConfig struct {
	// An oauth2 token source to use for authenticating to GCS.
	//
	// You probably want this one:
	//     http://godoc.org/golang.org/x/oauth2/google#DefaultTokenSource
	TokenSource oauth2.TokenSource

	// The value to set in User-Agent headers for outgoing HTTP requests. If
	// empty, a default will be used.
	UserAgent string

	// The HTTP transport to use for communication with GCS. If not supplied,
	// http.DefaultTransport will be used.
	Transport httputil.CancellableRoundTripper

	// The maximum amount of time to spend sleeping in a retry loop with
	// exponential backoff for failed requests. The default of zero disables
	// automatic retries.
	//
	// If you enable automatic retries, beware of the following:
	//
	//  *  Bucket.CreateObject will buffer the entire object contents in memory,
	//     so your object contents must not be too large to fit.
	//
	//  *  Bucket.NewReader needs to perform an additional round trip to GCS in
	//     order to find the latest object generation if you don't specify a
	//     particular generation.
	//
	//  *  Make sure your operations are idempotent, or that your application can
	//     tolerate it if not.
	//
	MaxBackoffSleep time.Duration

	// Loggers for GCS events, and (much more verbose) HTTP requests and
	// responses. If nil, no logging is performed.
	GCSDebugLogger  *log.Logger
	HTTPDebugLogger *log.Logger
}

// Open a connection to GCS.
func NewConn(cfg *ConnConfig) (c Conn, err error) {
	// Fix the user agent if there is none.
	userAgent := cfg.UserAgent
	if userAgent == "" {
		const defaultUserAgent = "github.com-jacobsa-gloud-gcs"
		userAgent = defaultUserAgent
	}

	// Choose the basic transport.
	transport := cfg.Transport
	if cfg.HTTPDebugLogger != nil {
		transport = http.DefaultTransport.(httputil.CancellableRoundTripper)
	}

	// Enable HTTP debugging if requested.
	if cfg.HTTPDebugLogger != nil {
		transport = httputil.DebuggingRoundTripper(transport, cfg.HTTPDebugLogger)
	}

	// Wrap the HTTP transport in an oauth layer.
	if cfg.TokenSource == nil {
		err = errors.New("You must set TokenSource.")
		return
	}

	transport = &oauth2.Transport{
		Source: cfg.TokenSource,
		Base:   transport,
	}

	// Set up the connection.
	c = &conn{
		client:          &http.Client{Transport: transport},
		userAgent:       userAgent,
		maxBackoffSleep: cfg.MaxBackoffSleep,
		debugLogger:     cfg.GCSDebugLogger,
	}

	return
}

type conn struct {
	client          *http.Client
	userAgent       string
	maxBackoffSleep time.Duration
	debugLogger     *log.Logger
}

func (c *conn) OpenBucket(
	ctx context.Context,
	name string) (b Bucket, err error) {
	b = newBucket(c.client, c.userAgent, name)

	// Enable retry loops if requested.
	if c.maxBackoffSleep > 0 {
		// TODO(jacobsa): Show the retries as distinct spans in the trace.
		b = newRetryBucket(c.maxBackoffSleep, b)
	}

	// Enable tracing if appropriate.
	if reqtrace.Enabled() {
		b = &reqtraceBucket{
			Wrapped: b,
		}
	}

	// Print debug output if requested.
	if c.debugLogger != nil {
		b = newDebugBucket(b, c.debugLogger)
	}

	// Attempt to make an innocuous request to the bucket, snooping for HTTP 403
	// errors that indicate bad credentials. This lets us warn the user early in
	// the latter case, with a more helpful message than just "HTTP 403
	// Forbidden". Similarly for bad bucket names that don't collide with another
	// bucket.
	_, err = b.ListObjects(ctx, &ListObjectsRequest{MaxResults: 1})

	if typed, ok := err.(*googleapi.Error); ok {
		switch typed.Code {
		case http.StatusForbidden:
			err = fmt.Errorf(
				"Bad credentials for bucket %q. Check the bucket name and your "+
					"credentials.",
				b.Name())

			return

		case http.StatusNotFound:
			err = fmt.Errorf("Unknown bucket %q", b.Name())
			return
		}
	}

	// Otherwise, don't interfere.
	err = nil

	return
}
<|endoftext|>


<commit_before>package signify

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/agl/ed25519"
	"io"
	"strings"
)

const (
	commentHdr = "untrusted comment: "
)

type rawEncryptedKey struct {
	PKAlgo      [2]byte
	KDFAlgo     [2]byte
	KDFRounds   uint32
	Salt        [16]byte
	Checksum    [8]byte
	Fingerprint [8]byte
	PrivateKey  [ed25519.PrivateKeySize]byte
}

type rawPublicKey struct {
	PKAlgo      [2]byte
	Fingerprint [8]byte
	PublicKey   [ed25519.PublicKeySize]byte
}

type rawSignature struct {
	PKAlgo      [2]byte
	Fingerprint [8]byte
	Signature   [ed25519.SignatureSize]byte
}

func ReadFile(r io.Reader) (comment string, content []byte, err error) {
	sc := bufio.NewScanner(r)

	if !sc.Scan() {
		return "", nil, fmt.Errorf("signify: read error %s", sc.Err())
	}
	comment = sc.Text()
	if !strings.HasPrefix(comment, commentHdr) {
		return "", nil, errors.New("signify: missing header")
	}
	comment = comment[len(commentHdr):]

	if !sc.Scan() {
		return "", nil, fmt.Errorf("signify: read error %s", sc.Err())
	}
	content, err = base64.StdEncoding.DecodeString(sc.Text())

	return
}

func ParsePrivateKey(raw []byte, passphrase string) (*rawEncryptedKey, error) {
	var ek rawEncryptedKey
	if err := binary.Read(bytes.NewReader(raw), binary.BigEndian, &ek); err != nil {
		return nil, err
	}
	return &ek, nil
}

func ParsePublicKey(raw []byte) (*rawPublicKey, error) {
	var pub rawPublicKey
	if err := binary.Read(bytes.NewReader(raw), binary.BigEndian, &pub); err != nil {
		return nil, err
	}
	return &pub, nil
}

func ParseSignature(raw []byte) (*rawSignature, error) {
	var sig rawSignature
	if err := binary.Read(bytes.NewReader(raw), binary.BigEndian, &sig); err != nil {
		return nil, err
	}
	return &sig, nil
}

<commit_msg>check PKAlgo/KDFAlgo<commit_after>package signify

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/agl/ed25519"
	"io"
	"strings"
)

const (
	commentHdr = "untrusted comment: "
)

var (
	algoEd = []byte{'E', 'd'}
	algoBcrypt = []byte{'B', 'K'}
)

type rawEncryptedKey struct {
	PKAlgo      [2]byte
	KDFAlgo     [2]byte
	KDFRounds   uint32
	Salt        [16]byte
	Checksum    [8]byte
	Fingerprint [8]byte
	PrivateKey  [ed25519.PrivateKeySize]byte
}

type rawPublicKey struct {
	PKAlgo      [2]byte
	Fingerprint [8]byte
	PublicKey   [ed25519.PublicKeySize]byte
}

type rawSignature struct {
	PKAlgo      [2]byte
	Fingerprint [8]byte
	Signature   [ed25519.SignatureSize]byte
}

func ReadFile(r io.Reader) (comment string, content []byte, err error) {
	sc := bufio.NewScanner(r)

	if !sc.Scan() {
		return "", nil, fmt.Errorf("signify: read error %s", sc.Err())
	}
	comment = sc.Text()
	if !strings.HasPrefix(comment, commentHdr) {
		return "", nil, errors.New("signify: missing header")
	}
	comment = comment[len(commentHdr):]

	if !sc.Scan() {
		return "", nil, fmt.Errorf("signify: read error %s", sc.Err())
	}
	content, err = base64.StdEncoding.DecodeString(sc.Text())

	return
}

func ParsePrivateKey(raw []byte, passphrase string) (*rawEncryptedKey, error) {

	if !bytes.Equal(algoEd, raw[:2]) {
		return nil, errors.New("signify: unknown public key algorithm")
	}
	if !bytes.Equal(algoBcrypt, raw[2:4]) {
		return nil, errors.New("signify: unknown kdf algorithm")
	}

	var ek rawEncryptedKey
	if err := binary.Read(bytes.NewReader(raw), binary.BigEndian, &ek); err != nil {
		return nil, err
	}
	return &ek, nil
}

func ParsePublicKey(raw []byte) (*rawPublicKey, error) {

	if !bytes.Equal(algoEd, raw[:2]) {
		return nil, errors.New("signify: unknown public key algorithm")
	}

	var pub rawPublicKey
	if err := binary.Read(bytes.NewReader(raw), binary.BigEndian, &pub); err != nil {
		return nil, err
	}
	return &pub, nil
}

func ParseSignature(raw []byte) (*rawSignature, error) {

	if !bytes.Equal(algoEd, raw[:2]) {
		return nil, errors.New("signify: unknown public key algorithm")
	}

	var sig rawSignature
	if err := binary.Read(bytes.NewReader(raw), binary.BigEndian, &sig); err != nil {
		return nil, err
	}
	return &sig, nil
}

<|endoftext|>


<commit_before>package engine

import (
	"github.com/vova616/gl"
	//"gl/glu"
	//"log"
	//"image/png"
	//"image"
	//"os"
	"log"

	"github.com/vova616/chipmunk/vect"
	//"glfw"
)

type OnAnimationEnd func(sprite *Sprite)

type Sprite struct {
	BaseComponent
	*Texture
	//buffer               gl.Buffer
	AnimationSpeed       float32
	texcoordsIndex       int
	endAnimation         int
	startAnimation       int
	animation            float32
	UVs                  AnimatedUV
	animMap              map[ID][2]int
	currentAnim          interface{}
	AnimationEndCallback OnAnimationEnd

	Tiling Vector

	Render bool

	Color Vector

	align AlignType
}

func NewSprite(tex *Texture) *Sprite {
	return NewSprite3(tex, AnimatedUV{NewUV(0, 0, 1, 1, float32(tex.Width())/float32(tex.Height()))})
}

func NewSprite2(tex *Texture, uv UV) *Sprite {
	return NewSprite3(tex, AnimatedUV{uv})
}

func NewSprite3(tex *Texture, uv AnimatedUV) *Sprite {

	sp := &Sprite{
		BaseComponent: NewComponent(),
		Texture:       tex,
		//buffer:         gl.GenBuffer(),
		AnimationSpeed: 1,
		endAnimation:   len(uv),
		UVs:            uv,
		Render:         true,
		Color:          Vector{1, 1, 1},
		align:          AlignCenter,
		Tiling:         Vector{1, 1, 0},
	}
	//sp.CreateVBO(uv...)

	return sp
}

func (p *Sprite) BindAnimations(animMap map[ID][2]int) {
	p.animMap = animMap
}

func (p *Sprite) SetAnimation(id ID) {
	a, e := p.animMap[id]
	if !e {
		panic("no such id")
	}
	p.currentAnim = id
	p.animation = float32(a[0])
	p.startAnimation = a[0]
	p.endAnimation = a[1]
}

func (p *Sprite) Align() AlignType {
	return p.align
}

func (p *Sprite) SetAlign(align AlignType) {
	p.align = align
}

func (p *Sprite) CurrentAnimation() interface{} {
	return p.currentAnim
}

func (sp *Sprite) OnComponentBind(binded *GameObject) {
	binded.Sprite = sp
}

/*
func (sp *Sprite) CreateVBO(uvs ...UV) {
	l := len(uvs)

	if l == 0 {
		sp.buffer.Bind(gl.ARRAY_BUFFER)
		gl.BufferData(gl.ARRAY_BUFFER, 1, []byte{1}, gl.STATIC_DRAW)
		return
	}

	lt := l * 12
	_ = lt
	data := make([]float32, 20*l)

	vertexCount := 0
	texcoordsIndex := lt * 4
	for i, uv := range uvs {

		yratio := float32(1)
		xratio := uv.Ratio
		ygrid := float32(-0.5)
		xgrid := float32(-uv.Ratio / 2)

		vertexCount += 4

		data[(i*12)+0] = xgrid
		data[(i*12)+1] = ygrid
		data[(i*12)+2] = 1
		data[(i*12)+3] = (xratio) + xgrid
		data[(i*12)+4] = ygrid
		data[(i*12)+5] = 1
		data[(i*12)+6] = (xratio) + xgrid
		data[(i*12)+7] = (yratio) + ygrid
		data[(i*12)+8] = 1
		data[(i*12)+9] = xgrid
		data[(i*12)+10] = (yratio) + ygrid
		data[(i*12)+11] = 1

		data[lt+(i*8)+0] = uv.U1
		data[lt+(i*8)+1] = uv.V2
		data[lt+(i*8)+2] = uv.U2
		data[lt+(i*8)+3] = uv.V2

		data[lt+(i*8)+4] = uv.U2
		data[lt+(i*8)+5] = uv.V1
		data[lt+(i*8)+6] = uv.U1
		data[lt+(i*8)+7] = uv.V1
	}

	sp.texcoordsIndex = texcoordsIndex
	sp.buffer.Bind(gl.ARRAY_BUFFER)
	gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, data, gl.STATIC_DRAW)
}
*/

func (sp *Sprite) Start() {

}

func (sp *Sprite) SetAnimationIndex(index int) {
	if index <= 0 {
		sp.animation = 0
	} else {
		sp.animation = float32(index % sp.endAnimation)
	}
}

var renders = 0

func (sp *Sprite) Update() {
	if sp.AnimationSpeed != 0 {
		if int(sp.animation) < sp.endAnimation {
			sp.animation += float32(float64(sp.AnimationSpeed) * DeltaTime())
		}
		if sp.animation >= float32(sp.endAnimation) {
			if sp.AnimationEndCallback != nil {
				sp.AnimationEndCallback(sp)
			}
			sp.animation = float32(sp.startAnimation)
		}
	}
	sp.UpdateShape()
	if renders != 0 && Debug && 1 == 2 {
		camera := GetScene().SceneBase().Camera
		log.Println(renders, camera.Transform().WorldPosition(), camera.Transform().Matrix())
	}
	renders = 0
}

/*
Todo: make this an interface.
*/
func (sp *Sprite) UpdateShape() {
	if sp.GameObject().Physics != nil {
		ph := sp.GameObject().Physics
		box := ph.Box
		cir := ph.Shape.GetAsCircle()

		scale := sp.Transform().WorldScale()
		ratio := sp.UVs[int(sp.animation)].Ratio
		scale.X *= ratio

		if box != nil {
			update := false
			if vect.Float(scale.Y) != box.Height || vect.Float(scale.X) != box.Width {
				box.Height = vect.Float(scale.Y)
				box.Width = vect.Float(scale.X)
				//box.Position = Vect{box.Width/2, box.Height/2}
				update = true
			}

			c := Align(sp.align)
			center := vect.Vect{vect.Float(c.X), vect.Float(c.Y)}
			center.X *= vect.Float(scale.X)
			center.Y *= vect.Float(scale.Y)

			if box.Position.X != center.X || box.Position.Y != center.Y {
				update = true
				box.Position.X, box.Position.Y = center.X, center.Y
			}

			if update {
				box.UpdatePoly()
				if !ph.Body.MomentIsInf() && box.Height != 0 && box.Width != 0 {
					ph.Body.SetMoment(vect.Float(box.Moment(float32(ph.Body.Mass()))))
				}
			}
		} else if cir != nil {
			update := false
			s := float32(0)
			if scale.X > scale.Y {
				s = scale.X
			} else {
				s = scale.Y
			}
			if float32(cir.Radius) != s/2 {
				cir.Radius = vect.Float(s / 2)
				update = true
			}

			c := Align(sp.align)
			center := vect.Vect{vect.Float(c.X), vect.Float(c.Y)}
			center.X *= vect.Float(s)
			center.Y *= vect.Float(s)

			if cir.Position.X != center.X || cir.Position.Y != center.Y {
				update = true
				cir.Position.X, cir.Position.Y = center.X, center.Y
			}

			if update {
				sp.GameObject().Physics.Body.UpdateShapes()
				if !ph.Body.MomentIsInf() && cir.Radius != 0 {
					//log.Println(sp.gameObject.name, cir.Radius, cir.Moment(float32(ph.Body.Mass())), scale.X, scale.Y, ph.Body.Mass(), cir.Position)
					ph.Body.SetMoment(vect.Float(cir.Moment(float32(ph.Body.Mass()))))
				}
			}
		}
	}
}

func Abs(val float32) float32 {
	if val < 0 {
		return -val
	}
	return val
}

func (sp *Sprite) Draw() {
	if sp.Texture != nil && sp.Render {
		/*
			Temporal camera distance check
		*/
		currentUV := sp.UVs[int(sp.animation)]
		if !InsideScreen(currentUV.Ratio, sp.Transform().WorldPosition(), sp.Transform().WorldScale()) {
			return
		}

		renders++

		TextureMaterial.Begin(sp.GameObject())

		mp := TextureMaterial.ProjMatrix
		mv := TextureMaterial.ViewMatrix
		mm := TextureMaterial.ModelMatrix
		tx := TextureMaterial.Texture
		ac := TextureMaterial.AddColor
		ti := TextureMaterial.Tiling
		of := TextureMaterial.Offset

		defaultVAO.Bind()

		v := Align(sp.align)
		v.X *= currentUV.Ratio

		camera := GetScene().SceneBase().Camera
		view := camera.InvertedMatrix()
		model := Identity()
		model.Scale(currentUV.Ratio, 1, 1)
		model.Translate(v.X, v.Y, 0)
		model.Mul(sp.GameObject().Transform().Matrix())

		mv.UniformMatrix4fv(false, view)
		mp.UniformMatrix4f(false, (*[16]float32)(camera.Projection))
		mm.UniformMatrix4fv(false, model)

		sp.Bind()
		tx.Uniform1i(0)

		ac.Uniform4f(sp.Color.X, sp.Color.Y, sp.Color.Z, 1)
		ti.Uniform2f((currentUV.U2-currentUV.U1)*sp.Tiling.X, (currentUV.V2-currentUV.V1)*sp.Tiling.Y)
		of.Uniform2f(currentUV.U1, currentUV.V1)

		gl.DrawArrays(gl.QUADS, 0, 4)

		TextureMaterial.End(sp.GameObject())
	}
}

func (sp *Sprite) DrawScreen() {
	if sp.Texture != nil && sp.Render {

		camera := GetScene().SceneBase().Camera
		pos := sp.Transform().WorldPosition()
		scale := sp.Transform().WorldScale()

		TextureMaterial.Begin(sp.GameObject())

		vert := TextureMaterial.Verts
		uv := TextureMaterial.UV
		mp := TextureMaterial.ProjMatrix
		mv := TextureMaterial.ViewMatrix
		mm := TextureMaterial.ModelMatrix
		tx := TextureMaterial.Texture
		ac := TextureMaterial.AddColor
		ti := TextureMaterial.Tiling
		of := TextureMaterial.Offset

		vert.EnableArray()
		uv.EnableArray()

		defaultBuffer.Bind(gl.ARRAY_BUFFER)

		vert.AttribPointer(3, gl.FLOAT, false, 0, uintptr(0))
		uv.AttribPointer(2, gl.FLOAT, false, 0, uintptr(12*4))

		currentUV := sp.UVs[int(sp.animation)]

		view := Identity()
		model := Identity()
		model.Scale(scale.X*currentUV.Ratio, scale.Y, 1)
		model.Translate((float32(Width)/2)+pos.X, (float32(Height)/2)+pos.Y, 1)

		mv.UniformMatrix4fv(false, view)
		mp.UniformMatrix4f(false, (*[16]float32)(camera.Projection))
		mm.UniformMatrix4fv(false, model)

		ti.Uniform2f((currentUV.U2-currentUV.U1)*sp.Tiling.X, (currentUV.V2-currentUV.V1)*sp.Tiling.Y)
		of.Uniform2f(currentUV.U1, currentUV.V1)

		sp.Bind()
		gl.ActiveTexture(gl.TEXTURE0)
		tx.Uniform1i(0)

		//ac.Uniform4f(1, 1, 1, 0)
		ac.Uniform4f(1, 1, 1, 1)

		gl.DrawArrays(gl.QUADS, 0, 4)

		sp.Unbind()
		vert.DisableArray()
		uv.DisableArray()

		TextureMaterial.End(sp.GameObject())
	}
}
<commit_msg>Fixed DrawScreen.<commit_after>package engine

import (
	"github.com/vova616/gl"
	//"gl/glu"
	//"log"
	//"image/png"
	//"image"
	//"os"
	"log"

	"github.com/vova616/chipmunk/vect"
	//"glfw"
)

type OnAnimationEnd func(sprite *Sprite)

type Sprite struct {
	BaseComponent
	*Texture
	//buffer               gl.Buffer
	AnimationSpeed       float32
	texcoordsIndex       int
	endAnimation         int
	startAnimation       int
	animation            float32
	UVs                  AnimatedUV
	animMap              map[ID][2]int
	currentAnim          interface{}
	AnimationEndCallback OnAnimationEnd

	Tiling Vector

	Render bool

	Color Vector

	align AlignType
}

func NewSprite(tex *Texture) *Sprite {
	return NewSprite3(tex, AnimatedUV{NewUV(0, 0, 1, 1, float32(tex.Width())/float32(tex.Height()))})
}

func NewSprite2(tex *Texture, uv UV) *Sprite {
	return NewSprite3(tex, AnimatedUV{uv})
}

func NewSprite3(tex *Texture, uv AnimatedUV) *Sprite {

	sp := &Sprite{
		BaseComponent: NewComponent(),
		Texture:       tex,
		//buffer:         gl.GenBuffer(),
		AnimationSpeed: 1,
		endAnimation:   len(uv),
		UVs:            uv,
		Render:         true,
		Color:          Vector{1, 1, 1},
		align:          AlignCenter,
		Tiling:         Vector{1, 1, 0},
	}
	//sp.CreateVBO(uv...)

	return sp
}

func (p *Sprite) BindAnimations(animMap map[ID][2]int) {
	p.animMap = animMap
}

func (p *Sprite) SetAnimation(id ID) {
	a, e := p.animMap[id]
	if !e {
		panic("no such id")
	}
	p.currentAnim = id
	p.animation = float32(a[0])
	p.startAnimation = a[0]
	p.endAnimation = a[1]
}

func (p *Sprite) Align() AlignType {
	return p.align
}

func (p *Sprite) SetAlign(align AlignType) {
	p.align = align
}

func (p *Sprite) CurrentAnimation() interface{} {
	return p.currentAnim
}

func (sp *Sprite) OnComponentBind(binded *GameObject) {
	binded.Sprite = sp
}

/*
func (sp *Sprite) CreateVBO(uvs ...UV) {
	l := len(uvs)

	if l == 0 {
		sp.buffer.Bind(gl.ARRAY_BUFFER)
		gl.BufferData(gl.ARRAY_BUFFER, 1, []byte{1}, gl.STATIC_DRAW)
		return
	}

	lt := l * 12
	_ = lt
	data := make([]float32, 20*l)

	vertexCount := 0
	texcoordsIndex := lt * 4
	for i, uv := range uvs {

		yratio := float32(1)
		xratio := uv.Ratio
		ygrid := float32(-0.5)
		xgrid := float32(-uv.Ratio / 2)

		vertexCount += 4

		data[(i*12)+0] = xgrid
		data[(i*12)+1] = ygrid
		data[(i*12)+2] = 1
		data[(i*12)+3] = (xratio) + xgrid
		data[(i*12)+4] = ygrid
		data[(i*12)+5] = 1
		data[(i*12)+6] = (xratio) + xgrid
		data[(i*12)+7] = (yratio) + ygrid
		data[(i*12)+8] = 1
		data[(i*12)+9] = xgrid
		data[(i*12)+10] = (yratio) + ygrid
		data[(i*12)+11] = 1

		data[lt+(i*8)+0] = uv.U1
		data[lt+(i*8)+1] = uv.V2
		data[lt+(i*8)+2] = uv.U2
		data[lt+(i*8)+3] = uv.V2

		data[lt+(i*8)+4] = uv.U2
		data[lt+(i*8)+5] = uv.V1
		data[lt+(i*8)+6] = uv.U1
		data[lt+(i*8)+7] = uv.V1
	}

	sp.texcoordsIndex = texcoordsIndex
	sp.buffer.Bind(gl.ARRAY_BUFFER)
	gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, data, gl.STATIC_DRAW)
}
*/

func (sp *Sprite) Start() {

}

func (sp *Sprite) SetAnimationIndex(index int) {
	if index <= 0 {
		sp.animation = 0
	} else {
		sp.animation = float32(index % sp.endAnimation)
	}
}

var renders = 0

func (sp *Sprite) Update() {
	if sp.AnimationSpeed != 0 {
		if int(sp.animation) < sp.endAnimation {
			sp.animation += float32(float64(sp.AnimationSpeed) * DeltaTime())
		}
		if sp.animation >= float32(sp.endAnimation) {
			if sp.AnimationEndCallback != nil {
				sp.AnimationEndCallback(sp)
			}
			sp.animation = float32(sp.startAnimation)
		}
	}
	sp.UpdateShape()
	if renders != 0 && Debug && 1 == 2 {
		camera := GetScene().SceneBase().Camera
		log.Println(renders, camera.Transform().WorldPosition(), camera.Transform().Matrix())
	}
	renders = 0
}

/*
Todo: make this an interface.
*/
func (sp *Sprite) UpdateShape() {
	if sp.GameObject().Physics != nil {
		ph := sp.GameObject().Physics
		box := ph.Box
		cir := ph.Shape.GetAsCircle()

		scale := sp.Transform().WorldScale()
		ratio := sp.UVs[int(sp.animation)].Ratio
		scale.X *= ratio

		if box != nil {
			update := false
			if vect.Float(scale.Y) != box.Height || vect.Float(scale.X) != box.Width {
				box.Height = vect.Float(scale.Y)
				box.Width = vect.Float(scale.X)
				//box.Position = Vect{box.Width/2, box.Height/2}
				update = true
			}

			c := Align(sp.align)
			center := vect.Vect{vect.Float(c.X), vect.Float(c.Y)}
			center.X *= vect.Float(scale.X)
			center.Y *= vect.Float(scale.Y)

			if box.Position.X != center.X || box.Position.Y != center.Y {
				update = true
				box.Position.X, box.Position.Y = center.X, center.Y
			}

			if update {
				box.UpdatePoly()
				if !ph.Body.MomentIsInf() && box.Height != 0 && box.Width != 0 {
					ph.Body.SetMoment(vect.Float(box.Moment(float32(ph.Body.Mass()))))
				}
			}
		} else if cir != nil {
			update := false
			s := float32(0)
			if scale.X > scale.Y {
				s = scale.X
			} else {
				s = scale.Y
			}
			if float32(cir.Radius) != s/2 {
				cir.Radius = vect.Float(s / 2)
				update = true
			}

			c := Align(sp.align)
			center := vect.Vect{vect.Float(c.X), vect.Float(c.Y)}
			center.X *= vect.Float(s)
			center.Y *= vect.Float(s)

			if cir.Position.X != center.X || cir.Position.Y != center.Y {
				update = true
				cir.Position.X, cir.Position.Y = center.X, center.Y
			}

			if update {
				sp.GameObject().Physics.Body.UpdateShapes()
				if !ph.Body.MomentIsInf() && cir.Radius != 0 {
					//log.Println(sp.gameObject.name, cir.Radius, cir.Moment(float32(ph.Body.Mass())), scale.X, scale.Y, ph.Body.Mass(), cir.Position)
					ph.Body.SetMoment(vect.Float(cir.Moment(float32(ph.Body.Mass()))))
				}
			}
		}
	}
}

func Abs(val float32) float32 {
	if val < 0 {
		return -val
	}
	return val
}

func (sp *Sprite) Draw() {
	if sp.Texture != nil && sp.Render {
		/*
			Temporal camera distance check
		*/
		currentUV := sp.UVs[int(sp.animation)]
		if !InsideScreen(currentUV.Ratio, sp.Transform().WorldPosition(), sp.Transform().WorldScale()) {
			return
		}

		renders++

		TextureMaterial.Begin(sp.GameObject())

		mp := TextureMaterial.ProjMatrix
		mv := TextureMaterial.ViewMatrix
		mm := TextureMaterial.ModelMatrix
		tx := TextureMaterial.Texture
		ac := TextureMaterial.AddColor
		ti := TextureMaterial.Tiling
		of := TextureMaterial.Offset

		defaultVAO.Bind()

		v := Align(sp.align)
		v.X *= currentUV.Ratio

		camera := GetScene().SceneBase().Camera
		view := camera.InvertedMatrix()
		model := Identity()
		model.Scale(currentUV.Ratio, 1, 1)
		model.Translate(v.X, v.Y, 0)
		model.Mul(sp.GameObject().Transform().Matrix())

		mv.UniformMatrix4fv(false, view)
		mp.UniformMatrix4f(false, (*[16]float32)(camera.Projection))
		mm.UniformMatrix4fv(false, model)

		sp.Bind()
		tx.Uniform1i(0)

		ac.Uniform4f(sp.Color.X, sp.Color.Y, sp.Color.Z, 1)
		ti.Uniform2f((currentUV.U2-currentUV.U1)*sp.Tiling.X, (currentUV.V2-currentUV.V1)*sp.Tiling.Y)
		of.Uniform2f(currentUV.U1, currentUV.V1)

		gl.DrawArrays(gl.QUADS, 0, 4)

		TextureMaterial.End(sp.GameObject())
	}
}

func (sp *Sprite) DrawScreen() {
	if sp.Texture != nil && sp.Render {

		camera := GetScene().SceneBase().Camera
		pos := sp.Transform().WorldPosition()
		scale := sp.Transform().WorldScale()

		TextureMaterial.Begin(sp.GameObject())

		mp := TextureMaterial.ProjMatrix
		mv := TextureMaterial.ViewMatrix
		mm := TextureMaterial.ModelMatrix
		tx := TextureMaterial.Texture
		ac := TextureMaterial.AddColor
		ti := TextureMaterial.Tiling
		of := TextureMaterial.Offset

		defaultVAO.Bind()

		currentUV := sp.UVs[int(sp.animation)]

		view := Identity()
		model := Identity()
		model.Scale(scale.X*currentUV.Ratio, scale.Y, 1)
		model.Translate((float32(Width)/2)+pos.X, (float32(Height)/2)+pos.Y, 1)

		mv.UniformMatrix4fv(false, view)
		mp.UniformMatrix4f(false, (*[16]float32)(camera.Projection))
		mm.UniformMatrix4fv(false, model)

		ti.Uniform2f((currentUV.U2-currentUV.U1)*sp.Tiling.X, (currentUV.V2-currentUV.V1)*sp.Tiling.Y)
		of.Uniform2f(currentUV.U1, currentUV.V1)

		sp.Bind()
		gl.ActiveTexture(gl.TEXTURE0)
		tx.Uniform1i(0)

		//ac.Uniform4f(1, 1, 1, 0)
		ac.Uniform4f(1, 1, 1, 1)

		gl.DrawArrays(gl.QUADS, 0, 4)

		TextureMaterial.End(sp.GameObject())
	}
}
<|endoftext|>


<commit_before>package functionaltests

import (
	c "github.com/couchbase/indexing/secondary/common"
	tc "github.com/couchbase/indexing/secondary/tests/framework/common"
	"github.com/couchbase/indexing/secondary/tests/framework/datautility"
	"github.com/couchbase/indexing/secondary/tests/framework/kvutility"
	"github.com/couchbase/indexing/secondary/tests/framework/secondaryindex"
	tv "github.com/couchbase/indexing/secondary/tests/framework/validation"
	"log"
	"os/user"
	"path/filepath"
	"testing"
	"time"
)

func TestLargeDocumentSize(t *testing.T) {
	log.Printf("In TestLargeDocumentSize()")

	u, _ := user.Current()
	datapath := filepath.Join(u.HomeDir, "testdata/TwitterFeed1.txt.gz")
	tc.DownloadDataFile(tc.IndexTypesTwitterFeed1JSONDataS3, datapath, true)
	largeDocs := datautility.LoadJSONFromCompressedFile(datapath, "id_str")
	UpdateKVDocs(largeDocs, docs)

	log.Printf("Length of docs and largeDocs = %d and %d", len(docs), len(largeDocs))

	bucketName := "default"
	index1 := "index_userscreenname"

	kvutility.SetKeyValues(largeDocs, bucketName, "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(index1, bucketName, indexManagementAddress, "", []string{"`user`.screen_name"}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	docScanResults := datautility.ExpectedScanAllResponse(docs, "user.screen_name")
	scanResults, err := secondaryindex.ScanAll(index1, bucketName, indexScanAddress, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan 1: ", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan 1:  result validation", t)
}

func TestFieldsWithSpecialCharacters(t *testing.T) {
	log.Printf("In TestFieldsWithSpecialCharacters()")

	var bucketName = "default"
	var indexName = "index_specialchar"
	var field = "splfield"

	docsToCreate := generateDocsWithSpecialCharacters(1000, "users.prod", field)
	UpdateKVDocs(docsToCreate, docs)
	var valueToLookup string
	for _, v := range docsToCreate {
		json := v.(map[string]interface{})
		valueToLookup = json[field].(string)
		break
	}

	kvutility.SetKeyValues(docsToCreate, bucketName, "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(indexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	log.Printf("Looking up for value %v", valueToLookup)
	docScanResults := datautility.ExpectedScanResponse_string(docs, field, valueToLookup, valueToLookup, 3)
	scanResults, err := secondaryindex.Lookup(indexName, bucketName, indexScanAddress, []interface{}{valueToLookup}, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)
}

func TestIndexNameValidation(t *testing.T) {
	log.Printf("In TestIndexNameValidation()")

	var bucketName = "default"
	var indexName = "ÌñÐÉx_utf8"
	var field = "balance"

	docsToCreate := generateDocs(1000, "users.prod")
	UpdateKVDocs(docsToCreate, docs)

	seed++
	log.Printf("Setting JSON docs in KV")
	kvutility.SetKeyValues(docsToCreate, "default", "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(indexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfNoError(err, "Expected index name validation error", t)
}

func TestSameFieldNameAtDifferentLevels(t *testing.T) {
	log.Printf("In TestSameFieldNameAtDifferentLevels()")

	var bucketName = "default"
	var indexName = "cityindex"
	var field = "city"

	docsToCreate := generateDocs(1000, "users.prod")
	UpdateKVDocs(docsToCreate, docs)
	docsToUpload := make(tc.KeyValues)

	for k, v := range docsToCreate {
		json := v.(map[string]interface{})
		address := json["address"].(map[string]interface{})
		city := address["city"].(string)
		json[field] = city
		address["city"] = "ThisIsNestedCity " + city
		docsToUpload[k] = json
	}

	seed++
	log.Printf("Setting JSON docs in KV")
	kvutility.SetKeyValues(docsToUpload, "default", "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(indexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	docScanResults := datautility.ExpectedScanResponse_string(docs, field, "A", "K", 3)
	scanResults, err := secondaryindex.Range(indexName, bucketName, indexScanAddress, []interface{}{"A"}, []interface{}{"K"}, 3, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)
}

func TestSameIndexNameInTwoBuckets(t *testing.T) {
	log.Printf("In TestSameIndexNameInTwoBuckets()")

	e := secondaryindex.DropAllSecondaryIndexes(indexManagementAddress)
	FailTestIfError(e, "Error in DropAllSecondaryIndexes", t)

	numOfBuckets := 2
	indexName := "b_idx"
	indexFields := [...]string{"age", "address.city"}
	bucketNames := [...]string{"default", "buck2"}
	proxyPorts := [...]string{"11212", "11213"}
	var bucketDocs [2]tc.KeyValues

	// Update default bucket ram to 256
	// Create two more buckets with ram 256 each
	// Add different docs to all 3 buckets
	// Create index on each of them
	// Query the indexes

	kvutility.FlushBucket(bucketNames[0], "", clusterconfig.Username, clusterconfig.Password, kvaddress)
	kvutility.EditBucket(bucketNames[0], "", clusterconfig.Username, clusterconfig.Password, kvaddress, "256")

	for i := 1; i < numOfBuckets; i++ {
		kvutility.CreateBucket(bucketNames[i], "sasl", "", clusterconfig.Username, clusterconfig.Password, kvaddress, "256", proxyPorts[i])
	}
	time.Sleep(30 * time.Second)

	log.Printf("Generating docs and Populating all the buckets")
	for i := 0; i < numOfBuckets; i++ {
		bucketDocs[i] = generateDocs(1000, "users.prod")
		kvutility.SetKeyValues(bucketDocs[i], bucketNames[i], "", clusterconfig.KVAddress)
		err := secondaryindex.CreateSecondaryIndex(indexName, bucketNames[i], indexManagementAddress, "", []string{indexFields[i]}, false, nil, true, defaultIndexActiveTimeout, nil)
		FailTestIfError(err, "Error in creating the index", t)
	}
	time.Sleep(3 * time.Second)

	// Scan index of first bucket
	docScanResults := datautility.ExpectedScanResponse_float64(bucketDocs[0], indexFields[0], 30, 50, 1)
	scanResults, err := secondaryindex.Range(indexName, bucketNames[0], indexScanAddress, []interface{}{30}, []interface{}{50}, 1, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan 1", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)

	// Scan index of second bucket
	docScanResults = datautility.ExpectedScanResponse_string(bucketDocs[1], indexFields[1], "F", "Q", 2)
	scanResults, err = secondaryindex.Range(indexName, bucketNames[1], indexScanAddress, []interface{}{"F"}, []interface{}{"Q"}, 2, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan 2", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)

	kvutility.EditBucket(bucketNames[0], "", clusterconfig.Username, clusterconfig.Password, kvaddress, "512")
	kvutility.DeleteBucket(bucketNames[1], "", clusterconfig.Username, clusterconfig.Password, kvaddress)
	time.Sleep(30 * time.Second) // Sleep after bucket create or delete

	tc.ClearMap(docs)
	UpdateKVDocs(bucketDocs[0], docs)
}

func generateDocsWithSpecialCharacters(numDocs int, prodFileName, field string) tc.KeyValues {
	prodfile := filepath.Join(proddir, prodFileName)
	docsToCreate := GenerateJsons(numDocs, seed, prodfile, bagdir)
	for k, v := range docsToCreate {
		json := v.(map[string]interface{})
		json[field] = randSpecialString(7)
		docsToCreate[k] = json
	}
	return docsToCreate
}
<commit_msg>Tests - Modifying TestIndexNameValidation to check for both valid(including #) and invalid index names<commit_after>package functionaltests

import (
	c "github.com/couchbase/indexing/secondary/common"
	tc "github.com/couchbase/indexing/secondary/tests/framework/common"
	"github.com/couchbase/indexing/secondary/tests/framework/datautility"
	"github.com/couchbase/indexing/secondary/tests/framework/kvutility"
	"github.com/couchbase/indexing/secondary/tests/framework/secondaryindex"
	tv "github.com/couchbase/indexing/secondary/tests/framework/validation"
	"log"
	"os/user"
	"path/filepath"
	"testing"
	"time"
)

func TestLargeDocumentSize(t *testing.T) {
	log.Printf("In TestLargeDocumentSize()")

	u, _ := user.Current()
	datapath := filepath.Join(u.HomeDir, "testdata/TwitterFeed1.txt.gz")
	tc.DownloadDataFile(tc.IndexTypesTwitterFeed1JSONDataS3, datapath, true)
	largeDocs := datautility.LoadJSONFromCompressedFile(datapath, "id_str")
	UpdateKVDocs(largeDocs, docs)

	log.Printf("Length of docs and largeDocs = %d and %d", len(docs), len(largeDocs))

	bucketName := "default"
	index1 := "index_userscreenname"

	kvutility.SetKeyValues(largeDocs, bucketName, "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(index1, bucketName, indexManagementAddress, "", []string{"`user`.screen_name"}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	docScanResults := datautility.ExpectedScanAllResponse(docs, "user.screen_name")
	scanResults, err := secondaryindex.ScanAll(index1, bucketName, indexScanAddress, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan 1: ", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan 1:  result validation", t)
}

func TestFieldsWithSpecialCharacters(t *testing.T) {
	log.Printf("In TestFieldsWithSpecialCharacters()")

	var bucketName = "default"
	var indexName = "index_specialchar"
	var field = "splfield"

	docsToCreate := generateDocsWithSpecialCharacters(1000, "users.prod", field)
	UpdateKVDocs(docsToCreate, docs)
	var valueToLookup string
	for _, v := range docsToCreate {
		json := v.(map[string]interface{})
		valueToLookup = json[field].(string)
		break
	}

	kvutility.SetKeyValues(docsToCreate, bucketName, "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(indexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	log.Printf("Looking up for value %v", valueToLookup)
	docScanResults := datautility.ExpectedScanResponse_string(docs, field, valueToLookup, valueToLookup, 3)
	scanResults, err := secondaryindex.Lookup(indexName, bucketName, indexScanAddress, []interface{}{valueToLookup}, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)
}

func TestIndexNameValidation(t *testing.T) {
	log.Printf("In TestIndexNameValidation()")

	var bucketName = "default"
	var validIndexName = "#primary-Index_test"
	var invalidIndexName = "ÌñÐÉx&(abc_%"
	var field = "balance"

	docsToCreate := generateDocs(1000, "users.prod")
	UpdateKVDocs(docsToCreate, docs)

	seed++
	log.Printf("Setting JSON docs in KV")
	kvutility.SetKeyValues(docsToCreate, "default", "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(invalidIndexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	errMsg := "Expected index name validation error for index " + invalidIndexName
	FailTestIfNoError(err, errMsg, t)
	log.Printf("Creation of index with invalid name %v failed as expected", invalidIndexName)

	err = secondaryindex.CreateSecondaryIndex(validIndexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	docScanResults := datautility.ExpectedScanResponse_string(docs, field, "$4", "$7", 3)
	scanResults, err := secondaryindex.Range(validIndexName, bucketName, indexScanAddress, []interface{}{"$4"}, []interface{}{"$7"}, 3, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)
}

func TestSameFieldNameAtDifferentLevels(t *testing.T) {
	log.Printf("In TestSameFieldNameAtDifferentLevels()")

	var bucketName = "default"
	var indexName = "cityindex"
	var field = "city"

	docsToCreate := generateDocs(1000, "users.prod")
	UpdateKVDocs(docsToCreate, docs)
	docsToUpload := make(tc.KeyValues)

	for k, v := range docsToCreate {
		json := v.(map[string]interface{})
		address := json["address"].(map[string]interface{})
		city := address["city"].(string)
		json[field] = city
		address["city"] = "ThisIsNestedCity " + city
		docsToUpload[k] = json
	}

	seed++
	log.Printf("Setting JSON docs in KV")
	kvutility.SetKeyValues(docsToUpload, "default", "", clusterconfig.KVAddress)

	err := secondaryindex.CreateSecondaryIndex(indexName, bucketName, indexManagementAddress, "", []string{field}, false, nil, true, defaultIndexActiveTimeout, nil)
	FailTestIfError(err, "Error in creating the index", t)

	docScanResults := datautility.ExpectedScanResponse_string(docs, field, "A", "K", 3)
	scanResults, err := secondaryindex.Range(indexName, bucketName, indexScanAddress, []interface{}{"A"}, []interface{}{"K"}, 3, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)
}

func TestSameIndexNameInTwoBuckets(t *testing.T) {
	log.Printf("In TestSameIndexNameInTwoBuckets()")

	e := secondaryindex.DropAllSecondaryIndexes(indexManagementAddress)
	FailTestIfError(e, "Error in DropAllSecondaryIndexes", t)

	numOfBuckets := 2
	indexName := "b_idx"
	indexFields := [...]string{"age", "address.city"}
	bucketNames := [...]string{"default", "buck2"}
	proxyPorts := [...]string{"11212", "11213"}
	var bucketDocs [2]tc.KeyValues

	// Update default bucket ram to 256
	// Create two more buckets with ram 256 each
	// Add different docs to all 3 buckets
	// Create index on each of them
	// Query the indexes

	kvutility.FlushBucket(bucketNames[0], "", clusterconfig.Username, clusterconfig.Password, kvaddress)
	kvutility.EditBucket(bucketNames[0], "", clusterconfig.Username, clusterconfig.Password, kvaddress, "256")

	for i := 1; i < numOfBuckets; i++ {
		kvutility.CreateBucket(bucketNames[i], "sasl", "", clusterconfig.Username, clusterconfig.Password, kvaddress, "256", proxyPorts[i])
	}
	time.Sleep(30 * time.Second)

	log.Printf("Generating docs and Populating all the buckets")
	for i := 0; i < numOfBuckets; i++ {
		bucketDocs[i] = generateDocs(1000, "users.prod")
		kvutility.SetKeyValues(bucketDocs[i], bucketNames[i], "", clusterconfig.KVAddress)
		err := secondaryindex.CreateSecondaryIndex(indexName, bucketNames[i], indexManagementAddress, "", []string{indexFields[i]}, false, nil, true, defaultIndexActiveTimeout, nil)
		FailTestIfError(err, "Error in creating the index", t)
	}
	time.Sleep(3 * time.Second)

	// Scan index of first bucket
	docScanResults := datautility.ExpectedScanResponse_float64(bucketDocs[0], indexFields[0], 30, 50, 1)
	scanResults, err := secondaryindex.Range(indexName, bucketNames[0], indexScanAddress, []interface{}{30}, []interface{}{50}, 1, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan 1", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)

	// Scan index of second bucket
	docScanResults = datautility.ExpectedScanResponse_string(bucketDocs[1], indexFields[1], "F", "Q", 2)
	scanResults, err = secondaryindex.Range(indexName, bucketNames[1], indexScanAddress, []interface{}{"F"}, []interface{}{"Q"}, 2, true, defaultlimit, c.SessionConsistency, nil)
	FailTestIfError(err, "Error in scan 2", t)
	err = tv.Validate(docScanResults, scanResults)
	FailTestIfError(err, "Error in scan result validation", t)

	kvutility.EditBucket(bucketNames[0], "", clusterconfig.Username, clusterconfig.Password, kvaddress, "512")
	kvutility.DeleteBucket(bucketNames[1], "", clusterconfig.Username, clusterconfig.Password, kvaddress)
	time.Sleep(30 * time.Second) // Sleep after bucket create or delete

	tc.ClearMap(docs)
	UpdateKVDocs(bucketDocs[0], docs)
}

func generateDocsWithSpecialCharacters(numDocs int, prodFileName, field string) tc.KeyValues {
	prodfile := filepath.Join(proddir, prodFileName)
	docsToCreate := GenerateJsons(numDocs, seed, prodfile, bagdir)
	for k, v := range docsToCreate {
		json := v.(map[string]interface{})
		json[field] = randSpecialString(7)
		docsToCreate[k] = json
	}
	return docsToCreate
}
<|endoftext|>


<commit_before>// Copyright 2015 Rana Ian. All rights reserved.
// Use of this source code is governed by The MIT License
// found in the accompanying LICENSE file.

package main

import (
	"flag"
	"github.com/ranaian/ora"
	"github.com/ranaian/ora/glg"
)

// Sample logging produced by glog
//
//	I0523 17:31:41.702365   97708 drv.go:411] OpenEnv 1
//	I0523 17:31:41.728377   97708 drv.go:411] OpenEnv 2
//	I0523 17:31:41.728377   97708 env.go:115] E2] OpenSrv (dbname orcl)
//	I0523 17:31:41.741390   97708 env.go:150] E2] OpenSrv (srvId 1)
//	I0523 17:31:41.741390   97708 srv.go:113] E2S1] OpenSes (username test)
//	I0523 17:31:41.762366   97708 ses.go:163] E2S1S1] Prep: SELECT CURRENT_TIMESTAMP FROM DUAL
//	I0523 17:31:41.762366   97708 rset.go:205] E2S1S1S1R0] open
//	I0523 17:31:41.762366   97708 ses.go:74] E2S1S1] Close
//	I0523 17:31:41.762366   97708 stmt.go:78] E2S1S1S1] Close
//	I0523 17:31:41.762366   97708 rset.go:57] E2S1S1S1R0] close
//	I0523 17:31:41.763365   97708 srv.go:63] E2S1] Close
//	I0523 17:31:41.763365   97708 env.go:68] E2] Close
//
func main() {

	// parse flags for glog (required)
	// consider specifying cmd line arg -alsologtostderr=true
	flag.Parse()

	// use the optional glog package for ora logging
	ora.Log = glg.Log

	env, _ := ora.GetDrv().OpenEnv()
	defer env.Close()
	srv, err := env.OpenSrv("orcl")
	defer srv.Close()
	if err != nil {
		panic(err)
	}
	ses, err := srv.OpenSes("test", "test")
	defer ses.Close()
	if err != nil {
		panic(err)
	}
	_, err = ses.PrepAndQry("SELECT CURRENT_TIMESTAMP FROM DUAL")
}
<commit_msg>added glg sample code<commit_after>// Copyright 2015 Rana Ian. All rights reserved.
// Use of this source code is governed by The MIT License
// found in the accompanying LICENSE file.

package main

import (
	"flag"
	"github.com/ranaian/ora"
	"github.com/ranaian/ora/glg"
)

// Sample logging produced by glog
//
//	I0523 17:31:41.702365   97708 drv.go:411] OpenEnv 1
//	I0523 17:31:41.728377   97708 drv.go:411] OpenEnv 2
//	I0523 17:31:41.728377   97708 env.go:115] E2] OpenSrv (dbname orcl)
//	I0523 17:31:41.741390   97708 env.go:150] E2] OpenSrv (srvId 1)
//	I0523 17:31:41.741390   97708 srv.go:113] E2S1] OpenSes (username test)
//	I0523 17:31:41.762366   97708 ses.go:163] E2S1S1] Prep: SELECT CURRENT_TIMESTAMP FROM DUAL
//	I0523 17:31:41.762366   97708 rset.go:205] E2S1S1S1R0] open
//	I0523 17:31:41.762366   97708 ses.go:74] E2S1S1] Close
//	I0523 17:31:41.762366   97708 stmt.go:78] E2S1S1S1] Close
//	I0523 17:31:41.762366   97708 rset.go:57] E2S1S1S1R0] close
//	I0523 17:31:41.763365   97708 srv.go:63] E2S1] Close
//	I0523 17:31:41.763365   97708 env.go:68] E2] Close
//
func main() {

	// parse flags for glog (required)
	// consider specifying cmd line arg -alsologtostderr=true
	flag.Parse()

	// use the optional glog package for ora logging
	ora.Log = glg.Log

	env, err := ora.GetDrv().OpenEnv()
	defer env.Close()
	if err != nil {
		panic(err)
	}
	srv, err := env.OpenSrv("orcl")
	defer srv.Close()
	if err != nil {
		panic(err)
	}
	ses, err := srv.OpenSes("test", "test")
	defer ses.Close()
	if err != nil {
		panic(err)
	}
	_, err = ses.PrepAndQry("SELECT CURRENT_TIMESTAMP FROM DUAL")
}
<|endoftext|>